【Spring Boot架构】AOP的两种动态代理(JDK和Cglib)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/sinat_27933301/article/details/102324348

JDK和Cglib两种动态代理方式区别

  1、java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。而Cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
  2、JDK动态代理只能对实现了接口的类生成代理,而不能针对类;Cglib是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,因为是继承,所以该类或方法最好不要声明成final 。
  3、Cglib一个目标类方法会生成两个代理方法,一个重写目标方法,并实现代理逻辑,还有一个直接调用目标类方法。

AOP的实现原理

想了解原理的可以看这篇【Spring教程】详解AOP的实现原理(动态代理),接下来我们直接通过示例讲如何使用。

引入AOP依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

AOP的配置

  1. 基于Spring的AOP写法
spring.aop.auto=true # 是否启用aop
spring.aop.proxy-target-class=false # 代理方式有接口使用jdk动态代理,如果没有接口使用cglib代理;设置为true时表示强制使用cglib代理
  1. 基于SpringBoot做法 @EnableAopProxyClass
exposeProxy属性表示如果使用true就可以使用AopContext对象获取当前代理对象,false则不能使用
proxyTargetClass true表示使用jdk的动态代理, false表示使用cglib代理

示例一(Cglib动态代理,默认)

1、BookDaoImpl

@Repository
public class BookDaoImpl implements BookDao {

    @Override
    public void addBook(String name, String author) {
        System.out.println("BookDaoImpl实现类:bookName:"+name+", bookAuthor:"+author);
    }
}

2、BookAop

@Component
@Aspect
public class BookAop {
    // 定义切入点
    public static final String POINT_CUT = "execution(* com.example.bootaop.dao..*.*(..))";

    @Before(POINT_CUT)
    public void before() {
        System.out.println("----------添加图书方法前[校验]-----------");
    }

    @After(POINT_CUT)
    public void after(JoinPoint jp) {
        System.out.println("----------添加图书成功后-----------");
        System.out.println(jp.getTarget().getClass());
        System.out.println(Arrays.asList(jp.getArgs()));
    }
}

3、BootAopApplication

@SpringBootApplication
public class BootAopApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext
                context = SpringApplication.run(BootAopApplication.class, args);
        BookDaoImpl bookDao = context.getBean(BookDaoImpl.class);
        System.out.println(bookDao.getClass());
        bookDao.addBook("神雕侠侣", "金庸");
        context.close();
    }
}

控制台输出

class com.example.bootaop.dao.BookDaoImpl$$EnhancerBySpringCGLIB$$2d857802
----------添加图书方法前[校验]-----------
BookDaoImpl实现类:bookName:神雕侠侣, bookAuthor:金庸
----------添加图书成功后-----------
class com.example.bootaop.dao.BookDaoImpl
[神雕侠侣, 金庸]

示例二(JDK动态代理,只能对实现了接口的类生成代理)

1、BookDao

@Repository
public class BookDaoImpl1 implements BookDao {
    @Override
    public void addBook(String name, String author) {

    }
}

2、BookDaoImpl1

@Repository
public class BookDaoImpl1 implements BookDao {
    @Override
    public void addBook(String name, String author) {

    }
}

3、BootAopApplication

@SpringBootApplication
public class BootAopApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext
                context = SpringApplication.run(BootAopApplication.class, args);
        BookDao bookDao = context.getBean("bookDaoImpl1", BookDao.class);//多个实现类时
        System.out.println(bookDao.getClass());
        bookDao.addBook("鹿鼎记", "金庸");
        context.close();
    }
}

配置文件增加:spring.aop.proxy-target-class=false

控制台输出

class com.sun.proxy.$Proxy61
----------添加图书方法前[校验]-----------
----------添加图书成功后-----------
class com.example.bootaop.dao.BookDaoImpl1
[鹿鼎记, 金庸]

猜你喜欢

转载自blog.csdn.net/sinat_27933301/article/details/102324348