深入浅出讲解Spring框架中AOP及动态代理的应用

目录
  • 一. Spring AOP
    • 1. 传统问题:
    • 2. 问题的解决策略:
    • 3. AOP优点:
  • 二.  动态代理
    • 1.JDK动态代理
    • 2. CGLIB代理

一. Spring AOP

面向切面编程(Aspect Oriented Programming,AOP)是软件编程思想发展到一定阶段的产物,是对面向对象编程(Object Oriented Programming,OOP)的有益补充, 目前已成为一种比较成熟的编程方式。AOP适用于具有横向逻辑的场所,如访问控制、事务管理、性能监测等。

1. 传统问题:

在传统的业务处理代码中,通常都会进行事务处理、日志记录等操作。虽然OOP可以通过组合或者继承的方式来达到代码的重用,但是比如实现日志记录时,代码还是会分散到不同的方法中。这样就会存在一个问题,如果想要关闭某个功能或者修改时,就必须要修改所有的相关方法。这不单单增加了开发人员的工作量,而且提高了代码的出错率。

2. 问题的解决策略:

为了解决这个问题,AOP思想随之产生。AOP采取横向抽取机制,将分散在各个方法中的重复代码提取出来,然后在程序编译或运行时,再将这些提取出来的代码应用到需要执行的地方。这种采用横向抽取机制的方式,是传统的OOP思想无法办到的,因为OOP只能实现父子关系的纵向的重用。虽然AOP是一种新的编程思想,却不是OOP的替代品,它只是OOP的延申和补充。

3. AOP优点:

AOP的使用让开发人员在编写业务逻辑时可以专心于核心业务,而不用过多地关注于其他业务逻辑的实现,这不但提高了开发效率,而且增强了代码的可维护性。

在AOP思想中,类于切面的关系如下图所示。我们可以看出,通过Aspect(切面)分别在Class1和Class2的方法中加入了事务、日志、权限和异常等功能。

二.  动态代理

通过学习我们知道了AOP中的代理就是由AOP框架动态生成的一个对象,该对象可以作为目标对象使用,对于面向切面编程,简单地说,就是在不改变原程序的基础上为代码段增加新的功能,对代码段进行增强处理。它的设计思想来源于代理设计模式,通常情况下调用对象的方法如下图。

在代理模式中可以为该对象设置一个代理对象,代理对象为function()提供一个代理方法,当通过代理对象的function()方法调用原对象的function()方法时,就可以在代理方法中添加新的功能,即增强处理。增强的功能既可以插到原对象的function()前面,也可以插到其后面(如虚线)

1.JDK动态代理

JDK动态代理是通过java.lang.reflect.Proxy类来实现的,可以调用Proxy类的newProxyInstance()方法来创建代理对象。对于使用业务接口的类,Spring框架会默认使用JDK动态代理来实现AOP。通过一个案例来演示。

1.  UserDao.java

package dao;

public interface UserDao {
    public void addUserDao();
    public void deleteUser();
}

2.  UserDaoImpl.java

package dao;

public class UserDaoImpl implements UserDao{
    @Override
    public void addUserDao() {
        System.out.println("添加用户");
    }

    @Override
    public void deleteUser() {
        System.out.println("删除用户");
    }
}

3.  MyAspect.java

package aspect;

public class MyAspect {
    public void check_permission(){
        System.out.println("----模拟检查访问----");
    }
    public void log(){
        System.out.println("----模拟记录日记----");
    }
}

4.  JdkProxy.java

package jdk;

import aspect.MyAspect;
import dao.UserDao;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * Jdk代理类
 */
public class JdkProxy implements InvocationHandler {
    //声明目标类接口
    private UserDao userdao;
//    创建代理方法
    public Object createProxy(UserDao userdao){
        this.userdao=userdao;
        //类加载器
        ClassLoader classLoader=JdkProxy.class.getClassLoader();
        //被代理对象实现的所有接口
        Class[] clazz=userdao.getClass().getInterfaces();
        //使用代理类进行增强,返回的是代理后的对象
        return Proxy.newProxyInstance(classLoader,clazz,this);
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //声明切面
        MyAspect myAspect=new MyAspect();
        //前增强
        myAspect.check_permission();
        //在目标上调用方法,并传入参数
        Object obj=method.invoke(userdao,args);
        //后增强
        myAspect.log();
        return obj;
    }
}

5.  Test.java

    @Test
    public void shouldAnswerWithTrue()
    {
        JdkProxy jdkProxy=new JdkProxy();
        UserDao userDao=new UserDaoImpl();
        UserDao userDao1=(UserDao) jdkProxy.createProxy(userDao);
        userDao1.addUserDao();
        System.out.println("\n-----------------------------分割线------------------------------------\n");
        userDao1.deleteUser();
    }

结果:

2. CGLIB代理

JDK 动态代理的使用非常简单,但它具有一定的局限性(使用动态代理的对象必须实现一个或多个接口)如果要对没有实现接口的类进行代理,那么可以使用CGLIB代理。

CGLIB(Code Generation Library)是一个高性能开源的代码生成包,它采用非常底层的字节码技术,对指定的目标类生成一个子类,并对子类进行增强。在Spring框架的核心包中已经集成了CGLIB所需要的包,所以开发中不需要另外导入jar包。

1.  BookDao.java

package dao;

public class BookDao {
    public void addBook(){
        System.out.println("添加书本");
    }
    public void deleteBook(){
        System.out.println("删除书本");
    }
}

2.  CglibProxy.java

package jdk;

import aspect.MyAspect;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CglibProxy implements MethodInterceptor {
    //代理方法
    public Object createProxy(Object target){
        Enhancer enhancer=new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        MyAspect myAspect=new MyAspect();
        myAspect.check_permission();
        Object o1=methodProxy.invokeSuper(proxy,args);
        myAspect.log();
        return o1;
    }
}

结果:

到此这篇关于深入浅出讲解Spring框架中AOP及动态代理的应用的文章就介绍到这了,更多相关Spring AOP及动态代理内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Spring中AOP概念与两种动态代理模式原理详解

    目录 1.概念 1.AOP技术简介 2.AOP的优势 3.Spring AOP术语 4.AOP 开发明确的事项 2.AOP底层实现 1.AOP 的动态代理技术: 3.基于cglib的动态代理代码 总结 1.概念 1.AOP技术简介 AOP 为Aspect Oriented Programming 的缩写,意思为面向切面编程,是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. AOP 是 OOP 的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一

  • Spring AOP中的JDK和CGLib动态代理哪个效率更高?

    一.背景 今天有小伙伴面试的时候被问到:Spring AOP中JDK 和 CGLib动态代理哪个效率更高? 二.基本概念 首先,我们知道Spring AOP的底层实现有两种方式:一种是JDK动态代理,另一种是CGLib的方式. 自Java 1.3以后,Java提供了动态代理技术,允许开发者在运行期创建接口的代理实例,后来这项技术被用到了Spring的很多地方. JDK动态代理主要涉及java.lang.reflect包下边的两个类:Proxy和InvocationHandler.其中,Invoc

  • Spring AOP注解失效的坑及JDK动态代理

    @Transactional @Async等注解不起作用 之前很多人在使用Spring中的@Transactional, @Async等注解时,都多少碰到过注解不起作用的情况. 为什么会出现这些情况呢?因为这些注解的功能实际上都是Spring AOP实现的,而其实现原理是通过代理实现的. JDK动态代理 以一个简单的例子理解一下JDK动态代理的基本原理: //目标类接口 public interface JDKProxyTestService { void run(); } //目标类 publ

  • Spring AOP手动实现简单动态代理的代码

    什么是AOP我们先来看一张图 图中A就是通知,比如你要给每个方法前都加一个before()方法,目标类的每一个方法叫joinpoint(切入点),每个切入点都会用到通知,把通知和切入点连起来,点成线,线成面,这就是切面,也就是AOP,下面我们来简单写个小例子来实现一下 目标类的接口 public interface UserService { public void addUser() ; public void updateUser(); public void deleteUser(); }

  • spring基础概念AOP与动态代理理解

    一.代理模式 代理模式的英文叫做Proxy或Surrogate,中文都可译为"代理",所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动.在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 以简单模拟事务的执行过程说明各种代理区别 1.1 静态代理 由程序员创建或由特定工具自动生成源代码,再对其编译.在程序运行前,代理类的.class文件就已经存在了. public interface PersonDao { vo

  • Spring AOP里的静态代理和动态代理用法详解

    什么是代理? 为某一个对象创建一个代理对象,程序不直接用原本的对象,而是由创建的代理对象来控制原对象,通过代理类这中间一层,能有效控制对委托类对象的直接访问,也可以很好地隐藏和保护委托类对象,同时也为实施不同控制策略预留了空间 什么是静态代理? 由程序创建或特定工具自动生成源代码,在程序运行前,代理类的.class文件就已经存在 通过将目标类与代理类实现同一个接口,让代理类持有真实类对象,然后在代理类方法中调用真实类方法,在调用真实类方法的前后添加我们所需要的功能扩展代码来达到增强的目的. 优点

  • 利用spring aop实现动态代理

    下面由我来给大家展示用spring aop实现动态代理的例子(电脑打印) 下面就看一下具体的代码: 先定义一个打印机的接口 package aop007_ComPrint; public interface Print { public void ColorPrint(); //彩色打印 public void WhitePrint(); //黑白打印 } 然后定义两个实现类,分别实现彩色打印和黑白打印 package aop007_ComPrint; public class ColorPri

  • 深入浅出讲解Spring框架中AOP及动态代理的应用

    目录 一. Spring AOP 1. 传统问题: 2. 问题的解决策略: 3. AOP优点: 二.  动态代理 1.JDK动态代理 2. CGLIB代理 一. Spring AOP 面向切面编程(Aspect Oriented Programming,AOP)是软件编程思想发展到一定阶段的产物,是对面向对象编程(Object Oriented Programming,OOP)的有益补充, 目前已成为一种比较成熟的编程方式.AOP适用于具有横向逻辑的场所,如访问控制.事务管理.性能监测等. 1.

  • 深入浅出讲解Spring框架中依赖注入与控制反转及应用

    目录 一. 概念: 1. 使用前: 2. 使用后: 二. 理解控制反转(Ioc): 三. IoC的应用方法 一. 概念: 依赖注入(Dependency Injection,DI)与控制反转(IoC)的含义相同,只不过是从两个角度描述的同一个概念.对于一个Spring初学者来说,这两种称呼都很难理解,我们通过简单的语言来描述这两个概念. 使用对比: 1. 使用前: 当某个Java对象(调用者)需要调用另一个Java对象(被调用者,就是被依赖对象)时,在传统模式下,调用者通常会采用"new被调用者

  • Java的Spring框架中AOP项目的一般配置和部署教程

    0.关于AOP 面向切面编程(也叫面向方面编程):Aspect Oriented Programming(AOP),是软件开发中的一个热点,也是Spring框架中的一个重要内容.利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率. AOP是OOP的延续. 主要的功能是:日志记录,性能统计,安全控制,事务处理,异常处理等等. 主要的意图是:将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过

  • 举例讲解Java的Spring框架中AOP程序设计方式的使用

    1.什么是AOP AOP是Aspect Oriented Programming的缩写,意思是面向方面编程,AOP实际是GoF设计模式的延续. 2.关于Spring AOP的一些术语:  A.切面(Aspect):在Spring AOP中,切面可以使用通用类或者在普通类中以@Aspect 注解(@AspectJ风格)来实现 B.连接点(Joinpoint):在Spring AOP中一个连接点代表一个方法的执行 C.通知(Advice):在切面的某个特定的连接点(Joinpoint)上执行的动作.

  • 如何在不使用spring框架中使用aop的功能

    目录 spring提供了两种方式的AOP使用 使用xml配置方式 使用注解方式 AspectJ简介 AspectJ的使用实例 不使用spring的aop功能实现日志输出 第一种 第二种:通过面向接口编程实现日志输出 第三种:使用java的代理机制进行日志输出 Spring框架的AOP机制可以让开发者把业务流程中的通用功能抽取出来,单独编写功能代码.在业务流程执行过程中,Spring框架会根据业务流程要求,自动把独立编写的功能代码切入到流程的合适位置. spring提供了两种方式的AOP使用 使用

  • 在Java Spring框架中使用的设计模式有哪些

    目录 1 简单工厂模式 2 工厂方法模式 3 单例模式 4 代理模式 好处 静态代理 动态代理 1 简单工厂模式 当A对象需要调用B对象的方法时,我们需要在A中new一个B的实例,我们把这种方式叫作硬编码耦合,缺点是一旦需求发生变化,比如需要使用C类来代替B时,就要改写A类的方法. 假如应用中有上千个类以硬编码的方式耦合了B,改就很头疼. 于是有了简单工厂模式,又叫静态工厂方法,就是由一个工厂类根据传入参数,动态决定应该创建哪个产品类. Spring中的BeanFactory就是简单工厂模式的体

  • 超细致讲解Spring框架 JdbcTemplate的使用

    目录 JdbcTemplate基本使用 1-JdbcTemplate基本使用-概述(了解) 2-JdbcTemplate基本使用-开发步骤(理解) 3-JdbcTemplate基本使用-快速入门代码实现(应用) 4-JdbcTemplate基本使用-spring产生模板对象分析(理解) 5-JdbcTemplate基本使用-spring产生模板对象代码实现(应用) 6-JdbcTemplate基本使用-spring产生模板对象代码实现 7-JdbcTemplate基本使用-常用操作-更新操作(应

  • 深入理解Java的Spring框架中的IOC容器

    Spring IOC的原型 spring框架的基础核心和起点毫无疑问就是IOC,IOC作为spring容器提供的核心技术,成功完成了依赖的反转:从主类的对依赖的主动管理反转为了spring容器对依赖的全局控制. 这样做的好处是什么呢? 当然就是所谓的"解耦"了,可以使得程序的各模块之间的关系更为独立,只需要spring控制这些模块之间的依赖关系并在容器启动和初始化的过程中将依据这些依赖关系创建.管理和维护这些模块就好,如果需要改变模块间的依赖关系的话,甚至都不需要改变程序代码,只需要将

  • Spring框架中 @Autowired 和 @Resource 注解的区别

    Spring框架中 @Autowired 和 @Resource 注解的区别 在 spring 框架中,除了使用其特有的注解外,使用基于 JSR-250 的注解,它包括 @PostConstruct, @PreDestroy 和 @Resource 注释. 首先,咱们简单了解 @PostConstruct 和 @PreDestroy 注释: 为了定义一个 bean 的安装和卸载,我们可以使用 init-method 和 destroy-method 参数简单的声明一下 ,其中 init-meth

随机推荐