0


Spring AOP(2)原理(代理模式和源码解析)

  1. 上篇文章学习了 Spring AOP 的应用,接下来我们来学习 Spring AOP 的原理,也就是 Spring 是如何实现 AOP 的。
  2. Spring AOP 是基于动态代理来实现 AOP 的,咱门学习内容主要分以下两部分:

1、代理模式

2、Spring AOP 源码 剖析


一、代理模式

  1. 代理模式,也叫 委托模式。

定义为其他对象提供一种代理以控制这个对象的访问。它的作用就是通过提供一个代理类,让我们在调用目标方法的时候,不再是直接对目标方法进行调用,而是通过代理类间接调用。

  1. 某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介作用。
  1. 使用代理前:

  1. 使用代理后:
  2. ![](https://i-blog.csdnimg.cn/direct/637bcff8852d4f81b10482181704d5f8.png)
  3. 生活中的代理:

艺人经纪人:广告商找艺人拍广告,需要经过经纪人,由经纪人来和艺人沟通。

房屋中介:房屋进行租赁时,卖方会把房屋授权给中介,由中介来代理看房,房屋咨询等服务。

经销商:厂商不直接对外销售产品,由经销商负责代理销售。

秘书/助理:合作伙伴找老板谈合作,需要先经过秘书/助理预约。

  1. 代理模式的主要角色:

1、Subject:业务接口类。可以是抽象类或者接口(不一定有)。

2、RealSubject:业务实现类。具体的业务执行,也就是被代理对象。

3、Proxy:代理类。RealSubject的代理。

比如 房屋出租:

  1. Subject:就是提前定义了房东做的事情,交给中介代理,也是中介要做的事情。
  2. RealSubject:房东。
  3. Proxy:中介。
  1. UML类图如下:
  2. ![](https://i-blog.csdnimg.cn/direct/6753b8885ba04550836314843f76c4fe.png)
  3. **代理模式可以在不修改被代理对象的基础上,通过扩展代理类**,进行一些功能的附加与增强。根据代理的创建时期,代理模式分为静态代理和动态代理。
  4. **静态代理**:由程序员创建代理类或特定工具自动生成源代码再对其编译,在程序运行前代理类的 .class 文件就已经存在了。
  5. **动态代理**:在程序运行时,运用反射机制动态创建而成。

二、静态代理

  1. 静态代理:在程序运行前,代理类的 .class文件 就已经存在了。(在出租房子之前,中介已经做好了相关的工作,就等租户来租房子了)。
  2. 我们通过代码来加深理解。以房租租赁为例:

1、定义接口(定义房东要做的事情,也是中介需要做的事情)

  1. public interface HouseSubject {
  2. void rentHouse();
  3. }

2、实现接口(房东出租房子)

  1. public class RealHouseSubject implements HouseSubject{
  2. @Override
  3. public void rentHouse() {
  4. System.out.println("我是房东, 我出租房子");
  5. }
  6. }

3、代理(中介,帮房东出租房子)

  1. public class HouseProxy implements HouseSubject{
  2. private HouseSubject target;
  3. public HouseProxy(HouseSubject target) {
  4. this.target = target;
  5. }
  6. @Override
  7. public void rentHouse() {
  8. //代理前
  9. System.out.println("我是中介, 开始代理");
  10. //出租房子
  11. target.rentHouse();;
  12. //代理后
  13. System.out.println("我是中介, 结束代理");
  14. }
  15. }

4、使用

  1. public class Main {
  2. public static void main(String[] args) {
  3. HouseSubject subject = new RealHouseSubject();
  4. //创建代理类
  5. HouseProxy houseProxy = new HouseProxy(subject);
  6. //通过代理类访问⽬标⽅法
  7. houseProxy.rentHouse();
  8. }
  9. }
  1. 运行结果:

  1. 上面这个代理实现方式就是静态代理(仿佛啥也没干)。从上述程序可以看出,虽然静态代理也完成了对目标对象的代理,但是由于代码都写死了,对目标对象的每个方法的增强都是手动完成的,非常不灵活。所以日常开发几乎看不到静态代理的场景。
  2. 接下来新增需求:中介又新增了其他业务:代理房屋出售。我们就需要对上述代码进行修改。

1、接口定义修改:

  1. public interface HouseSubject {
  2. void rentHouse();
  3. void saleHouse();
  4. }

2、接口实现修改

  1. public class RealHouseSubject implements HouseSubject{
  2. @Override
  3. public void rentHouse() {
  4. System.out.println("我是房东, 我出租房子");
  5. }
  6. @Override
  7. public void saleHouse() {
  8. System.out.println("我是房东, 我出售房子");
  9. }
  10. }

3、代理类修改

  1. public class HouseProxy implements HouseSubject{
  2. private HouseSubject target;
  3. public HouseProxy(HouseSubject target) {
  4. this.target = target;
  5. }
  6. @Override
  7. public void rentHouse() {
  8. //代理前
  9. System.out.println("我是中介, 开始代理");
  10. //出租房子
  11. target.rentHouse();;
  12. //代理后
  13. System.out.println("我是中介, 结束代理");
  14. }
  15. @Override
  16. public void saleHouse() {
  17. //代理前
  18. System.out.println("我是中介, 开始代理");
  19. //出租房子
  20. target.rentHouse();;
  21. //代理后
  22. System.out.println("我是中介, 结束代理");
  23. }
  24. }

4、使用

  1. public class Main {
  2. public static void main(String[] args) {
  3. HouseSubject subject = new RealHouseSubject();
  4. //创建代理类
  5. HouseProxy houseProxy = new HouseProxy(subject);
  6. //通过代理类访问⽬标⽅法
  7. houseProxy.rentHouse();
  8. System.out.println("=========");
  9. houseProxy.saleHouse();
  10. }
  11. }
  1. 运行结果:

  1. 从上述代码可以看出,我们修改接口(Subject)和业务实现类(RealSubject),还需要修改代理类(Proxy)。
  2. 同样的,如果新增接口(Subject)和业务实现类(RealSubject),也需要对每一个业务实现类新增代理类(Proxy)。
  3. 既然代理的流程是一样的,有没有一种办法,让他们通过一个代理类来实现呢?这就需要用到动态代理技术了。

三、动态代理

  1. 相比于静态代理来说,动态代理更加灵活。**我们不需要针对每个目标对象都单独创建一个代理对象,而是把这个创建代理对象的工作推迟到程序运行时由JVM来实现**。也就是说动态代理在程序运行时,根据需要动态创建生成。
  2. 比如房屋中介,我不需要提前预测都有哪些业务,而是业务来了我再根据情况创建。
  3. 先看代码再来理解。Java也对动态代理进行了实现,并给我们提供一些API,常见的实现方式有两种:
  4. **1JDK动态代理**
  5. **2CGLIB动态代理**

动态代理在我们日常开发中使用的相对较少,但是在框架中几乎是必用的一门技术。学会了动态代理之后,对于我们理解和学习各种框架的原理也非常有帮助。

1、JDK动态代理

(1)JDK动态代理实现步骤

1、定义一个接口及其实现类(静态代理中的 HouseSubject 和 RealHouseSubject)。

2、自定义 InvocationHandler 并重写 invoke 方法,在 invoke 方法中我们会调用目标方法(被代理类的方法),并自定义一些处理逻辑。

3、通过 Proxy.newProxyInstance(ClassLoader, Class<?>[ ] Interfaces, InvocationHandler h)方法创建代理对象。

(2)定义JDK动态代理类

  1. 创建 JDKInvocationHandler 实现 InvocationHandler 接口:
  1. public class JDKInvocationHandler implements InvocationHandler {
  2. //目标对象,即被代理的对象
  3. private Object target;
  4. public JDKInvocationHandler(Object target) {
  5. this.target = target;
  6. }
  7. @Override
  8. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  9. //代理增强内容
  10. System.out.println("我是中介,开始代理");
  11. //通过反射调用被代理类的方法
  12. Object result = method.invoke(target, args);
  13. //代理增强内容
  14. System.out.println("我是中介,结束代理");
  15. return result;
  16. }
  17. }
  1. 创建一个代理对象并使用:
  1. public class Main {
  2. public static void main(String[] args) {
  3. /**
  4. * JDK动态代理
  5. */
  6. //创建⼀个代理类:通过被代理类、被代理实现的接⼝、⽅法调⽤处理器来创建
  7. RealHouseSubject target = new RealHouseSubject();//目标对象
  8. /**
  9. * newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
  10. * loader:加载我们的被代理类的ClassLoad
  11. * interfaces:要实现的接口
  12. * h:代理要做的事情,需要实现 InvocationHandler 这个接口
  13. */
  14. HouseSubject proxy = (HouseSubject) Proxy.newProxyInstance(
  15. target.getClass().getClassLoader(),
  16. new Class[]{HouseSubject.class},
  17. new JDKInvocationHandler(target)
  18. );
  19. proxy.rentHouse();
  20. System.out.println("==============");
  21. proxy.saleHouse();
  22. }
  23. }
  1. 运行程序,结果如下:

  1. 假设代理的是类,而不是对象,代码如下:
  1. public class Main {
  2. public static void main(String[] args) {
  3. RealHouseSubject target = new RealHouseSubject();
  4. RealHouseSubject proxy = (RealHouseSubject) Proxy.newProxyInstance(
  5. target.getClass().getClassLoader(),
  6. new Class[]{RealHouseSubject.class},
  7. new JDKInvocationHandler(target)
  8. );
  9. proxy.rentHouse();
  10. System.out.println("==============");
  11. proxy.saleHouse();
  12. }
  13. }
  1. 运行程序,结果如下:(报错了)

  1. **报错原因**:RealHouseSubject is not an interfaceRealHouseSubject 类不是接口),**说明JDK 动态代理只能代理接口,不能代理类**,不然会报错。

(3)代码简单讲解

  1. 主要是学习API的使用,我们按照 Java API 的规范来使用即可。

1、InvocationHandler:

  1. InvocationHandler 接口是 Java 动态代理的关键接口之一,它定义了一个单一方法 invoke(),用于处理被代理对象的方法调用。
  1. public interface InvocationHandler {
  2. /**
  3. * 参数说明
  4. * proxy:被代理对象
  5. * method:被代理对象需要实现的⽅法,即其中需要重写的⽅法
  6. * args:method所对应⽅法的参数
  7. */
  8. public Object invoke(Object proxy, Method method, Object[] args)
  9. throws Throwable;
  10. }
  1. 通过实现 InvocationHandler 接口,可以对被代理对象的方法进行功能增强。

2、Proxy:

  1. Proxy 类中使用频率最高的方法:newProxyInstance(),这个方法主要用来生成一个代理对象。
  1. public static Object newProxyInstance(ClassLoader loader,
  2. Class<?>[] interfaces,
  3. InvocationHandler h)
  4. throws IllegalArgumentException
  5. {
  6. //...代码省略
  7. }
  1. 这个方法一共有 3 个参数:

loader:类加载器,用于加载被代理对象。

interface:被代理类实现的一些接口(这个参数的定义,也决定了JDK动态代理只能代理实现了接口的一些类)。

h:代理要做的事情,实现 InvocationHandler 接口的对象。

2、CGLIB动态代理

  1. JDK动态代理有一个**最致命的问题**,是只能代理实现了接口的类。
  2. 有些场景下,我们的业务码是直接实现的,并没有接口定义。为了解决这个问题,我们可以用 CGLIB 动态代理机制来解决。
  3. CGLIBCode Generation Library)是一个基于 ASM 的字节码生产库,它允许我们在运行时对字节码进行修改和动态生成。
  4. CGLIB 通过继承方式实现代理,很多知名的开源框架都使用到了 CGLIB。例如 Spring 中的 AOP 模块中:如果目标对象实现了接口,则默认采用 JDK 动态代理,否则采用 CGLIB 动态代理。(**其中 Spring 是基于动态代理实现的,动态代理是基于反射实现的**)

(1)CGLIB 动态代理类实现步骤

1、定义一个类(被代理类)。

2、自定义 MethodInterceptor 并重写 intercept 方法,intercept 用于增强目标方法,和 JDK 动态代理中的 invoke 方法类似。

3、通过 Enhancer 类的 create() 创建代理类。

  1. 接下来看实现:

(2)添加依赖

  1. JDK 动态代理不同,CGLIBCode Generation Library)实际是属于一个开源项目,如果你要使用它的话,需要手动添加相关依赖。
  1. <dependency>
  2. <groupId>cglib</groupId>
  3. <artifactId>cglib</artifactId>
  4. <version>3.3.0</version>
  5. </dependency>

(3)自定义MethodInterceptor(方法拦截器)

  1. 实现 MethodInterceptor 接口:
  1. import org.springframework.cglib.proxy.MethodInterceptor;
  2. import java.lang.reflect.Method;
  3. public class CGLibInterceptor implements MethodInterceptor {
  4. private Object target;
  5. public CGLibInterceptor(Object target) {
  6. this.target = target;
  7. }
  8. /**
  9. * 调用代理对象的方法
  10. */
  11. @Override
  12. public Object intercept(Object obj, Method method, Object[] args, org.springframework.cglib.proxy.MethodProxy proxy) throws Throwable {
  13. //代理增强内容
  14. System.out.println("我是中介,开始代理");
  15. Object result = method.invoke(target, args);
  16. //代理增强内容
  17. System.out.println("我是中介,结束代理");
  18. return result;
  19. }
  20. }

(4)创建代理类,并使用

  1. 代理接口:
  1. public class Main {
  2. public static void main(String[] args) {
  3. //目标对象
  4. HouseSubject target = new RealHouseSubject();
  5. HouseSubject proxy = (HouseSubject) Enhancer.create(target.getClass(), new CGLibInterceptor(target));
  6. proxy.rentHouse();
  7. System.out.println("=============");
  8. proxy.saleHouse();
  9. }
  10. }
  1. 运行程序,执行结果如下:

  1. 代理类:
  1. public class Main {
  2. public static void main(String[] args) {
  3. //目标对象
  4. HouseSubject target = new RealHouseSubject();
  5. RealHouseSubject proxy = (RealHouseSubject) Enhancer.create(target.getClass(), new CGLibInterceptor(target));
  6. proxy.rentHouse();
  7. System.out.println("=============");
  8. proxy.saleHouse();
  9. }
  10. }
  1. 运行程序,执行结果如下:

(5)代码简单讲解

1、MethodInterceptor

  1. MethodInterceptor JDK动态代理中的 InvocationHandler 类似,它只定义了一个方法 intercept(),用于增强目标方法。
  1. public interface MethodInterceptor extends Callback {
  2. /**
  3. * 参数说明:
  4. * o: 被代理的对象
  5. * method: ⽬标⽅法(被拦截的⽅法, 也就是需要增强的⽅法)
  6. * objects: ⽅法⼊参
  7. * methodProxy: ⽤于调⽤原始⽅法
  8. */
  9. Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable;
  10. }

**2、Enhancer.create()**:

  1. public static Object create(Class type, Callback callback) {
  2. //...代码省略
  3. }
  1. **type**:被代理类的类型(类或接口)
  2. **callback**:自定义方法拦截器 MethodInterceptor

四、Spring AOP 源码剖析(了解)

  1. Spring AOP 主要基于两种方式实现的:JDK CGLIB 的方式。
  2. Spring 源码过于复杂,我们只摘出一些主要内容,以了解为主
  3. Spring 对于 AOP 的实现,基本都是靠 AnnotationAwareAspectJAutoProxyCreator 去完成 生成代理对象的逻辑在父类 AbstractAutoProxyCreator 中。
  1. protected Object createProxy(Class<?> beanClass,@Nullable String beanName,
  2. @Nullable Object[]specificInterceptors,TargetSource targetSource){
  3. if(this.beanFactory instanceof ConfigurableListableBeanFactory){
  4. AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory)
  5. this.beanFactory,beanName,beanClass);
  6. }
  7. //创建代理⼯⼚
  8. ProxyFactory proxyFactory=new ProxyFactory();
  9. proxyFactory.copyFrom(this);
  10. /**
  11. * 检查proxyTargetClass属性值,spring默认为false
  12. * proxyTargetClass 检查接⼝是否对类代理, ⽽不是对接⼝代理
  13. * 如果代理对象为类, 设置为true, 使⽤cglib代理
  14. */
  15. if(!proxyFactory.isProxyTargetClass()){
  16. //是否有设置cglib代理
  17. if(shouldProxyTargetClass(beanClass,beanName)){
  18. //设置proxyTargetClass为true,使⽤cglib代理
  19. proxyFactory.setProxyTargetClass(true);
  20. }else{
  21. /**
  22. * 如果beanClass实现了接⼝,且接⼝⾄少有⼀个⾃定义⽅法,则使⽤JDK代理
  23. * 否则CGLIB代理(设置ProxyTargetClass为true )
  24. * 即使我们配置了proxyTargetClass=false, 经过这⾥的⼀些判断还是可能会将其
  25. 设为true
  26. */
  27. evaluateProxyInterfaces(beanClass,proxyFactory);
  28. }
  29. }
  30. Advisor[]advisors=buildAdvisors(beanName,specificInterceptors);
  31. proxyFactory.addAdvisors(advisors);
  32. proxyFactory.setTargetSource(targetSource);
  33. customizeProxyFactory(proxyFactory);
  34. proxyFactory.setFrozen(this.freezeProxy);
  35. if(advisorsPreFiltered()){
  36. proxyFactory.setPreFiltered(true);
  37. }
  38. // Use original ClassLoader if bean class not locally loaded in overriding class loader
  39. ClassLoader classLoader =getProxyClassLoader();
  40. if(classLoader instanceof SmartClassLoader&&classLoader != beanClass.getClassLoader()){
  41. classLoader=((SmartClassLoader)classLoader).getOriginalClassLoader();
  42. }
  43. //从代理⼯⼚中获取代理
  44. return proxyFactory.getProxy(classLoader);
  45. }
  1. 代理工厂有一个重要的属性:proxyTargetClass,默认值为false。也可以通过程序设置

proxyTargetClass⽬标对象代理⽅式false实现了接口jdk代理false未实现接口(只有实现类)cglib代理true实现了接口cglib代理true未实现接口(只有实现类)cglib代理
可以通过 @EnableAspectJAutoProxy(proxyTargetClass = true) 来设置。

  1. 注意:

Spring 默认 proxyTargetClass:false,会分为两种情况:

  1. **实现了接口**:使用 JDK 代理。
  2. **普通类**: 使用 CGLIB 代理。

Spring Boot 2.X 开始,默认使用 proxyTargetClass:true

  1. **默认使用 CGLIB 代理**
  1. SpringBoot设置 @EnableAspectJAutoProxy 无效,因为 Spring Boot 默认使用 AopAutoConfiguration 进行装配。
  2. 可以通过配置项 spring.aop.proxy-target-class=false 来进行修改,设置为 jdk 代理。
  3. 使用 context.getBean() 需要添加注解,使 HouseProxyRealHouseSubject Spring 管理。测试 AOP 代理,需要把这些类交给 AOP 管理(自定义注解或使用 @Aspect
  4. 我们现在从源码中点进去看看代理工厂的代码:
  1. public class ProxyFactory extends ProxyCreatorSupport {
  2. //...代码省略
  3. //获取代理
  4. public Object getProxy(@Nullable ClassLoader classLoader) {
  5. //分两步 先createAopProxy,后getProxy
  6. return createAopProxy().getProxy(classLoader);
  7. }
  8. protected final synchronized AopProxy createAopProxy() {
  9. if (!this.active) {
  10. activate();
  11. }
  12. return getAopProxyFactory().createAopProxy(this);
  13. }
  14. //...代码省略
  15. }
  1. createAopProxy 的实现在 DefaultAopProxyFactory
  1. public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
  2. //...代码省略
  3. @Override
  4. public AopProxy createAopProxy(AdvisedSupport config) throws
  5. AopConfigException {
  6. /**
  7. * 根据proxyTargetClass判断
  8. * 如果⽬标类是接⼝, 使⽤JDK动态代理
  9. * 否则使⽤cglib动态代理
  10. */
  11. if (!NativeDetector.inNativeImage() &&
  12. (config.isOptimize() || config.isProxyTargetClass() ||
  13. hasNoUserSuppliedProxyInterfaces(config))) {
  14. Class<?> targetClass = config.getTargetClass();
  15. if (targetClass == null) {
  16. throw new AopConfigException("TargetSource cannot determine
  17. target class:" +
  18. "Either an interface or a target is required for proxy
  19. creation. ");
  20. }
  21. if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) ||
  22. ClassUtils.isLambdaClass(targetClass)) {
  23. return new JdkDynamicAopProxy(config);
  24. }
  25. return new ObjenesisCglibAopProxy(config);
  26. } else {
  27. return new JdkDynamicAopProxy(config);
  28. }
  29. }
  30. //...代码省略
  31. }
  1. 接下来就是创建代理了

JDK动态代理:

  1. final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
  2. //...代码省略
  3. @Override
  4. public Object getProxy(@Nullable ClassLoader classLoader) {
  5. if (logger.isTraceEnabled()) {
  6. logger.trace("Creating JDK dynamic proxy: " +
  7. this.advised.getTargetSource());
  8. }
  9. return Proxy.newProxyInstance(determineClassLoader(classLoader),
  10. this.proxiedInterfaces, this);
  11. }
  12. //...代码省略
  13. }

CGLIB动态代理:

  1. class CglibAopProxy implements AopProxy, Serializable {
  2. //...代码省略
  3. @Override
  4. public Object getProxy(@Nullable ClassLoader classLoader) {
  5. //...代码省略
  6. // Configure CGLIB Enhancer...
  7. Enhancer enhancer = createEnhancer();
  8. // Generate the proxy class and create a proxy instance.
  9. return createProxyClassAndInstance(enhancer, callbacks);
  10. }
  11. //...代码省略
  12. }

五、常见面试题

1、什么是 AOP?

  1. AOP 面向切面编程,也是一种思想,切面指的是某一类特定问题,所以 AOP 也可以理解为 面向切面编程。

2、Spring AOP的实现方式有哪些?

(1)基于注解(@Aspect 或 自定义注解)

(2)基于 xml

(3)基于代理

3、Spring AOP 的实现原理?

  1. 基于动态代理实现的,其中的动态代理有两种形式:(1JDK 2CGLIB

4、Spring 使用的是哪种代理方式?

  1. Spring proxyTargetClass 默认为:false,其中:实现了接口,使用 JDK 代理;普通类:使用CGLIB代理。
  2. Spring Boot 2.X 之后,proxyTargetClass 默认为:true,默认使用 CGLIB 代理

  1. 现在我们测试一下:当这个值为 true 时,则使用的是动态代理
  2. ![](https://i-blog.csdnimg.cn/direct/80b5aa4fb47d4ccf9622b33a7084f322.png)
  1. @SpringBootApplication
  2. public class SpringAopApplication {
  3. public static void main(String[] args) {
  4. ApplicationContext context = SpringApplication.run(SpringAopApplication.class, args);
  5. //代理类
  6. TestController bean = context.getBean(TestController.class);
  7. System.out.println(bean);
  8. }
  9. }
  1. 要打断电才能观察到结果,如图:

  1. 我们获取Spring管理的对象,打断点,观察对象名称,如图:

  1. 可以看到,是 CGLIB代理。

当值设为 false 时;就要看代理对象是不是接口了,是接口用的就是JDK代理,代理对象是类就是CGLIB代理。

  1. 因为要代理接口,所以现在重新创建一个接口,内容如下:
  1. public interface IFace {
  2. void test();
  3. }
  1. 再创建一个成 Controller 类,实现上面这个类
  1. @RequestMapping("/test2")
  2. @RestController
  3. public class TestController2 implements IFace{
  4. @MyAspect
  5. @RequestMapping("t1")
  6. @Override
  7. public void test() {
  8. System.out.println("测试测试");
  9. }
  10. }
  1. main方法如下:
  1. @SpringBootApplication
  2. public class SpringAopApplication {
  3. public static void main(String[] args) {
  4. ApplicationContext context = SpringApplication.run(SpringAopApplication.class, args);
  5. //代理类
  6. TestController bean = context.getBean(TestController.class);
  7. System.out.println(bean);
  8. //代理接口
  9. IFace iFace = (IFace) context.getBean("testController2");
  10. System.out.println(iFace);
  11. }
  12. }
  1. 现在看看Spring对象,任然要使用断点才能看到,如图:

  1. 看看bean对象,如图:

5、JDK 和 CGLIB 的区别?

  1. 使用JDK 动态代理只能代理接口。
  2. 使用 CGLIB 动态代理 既可以代理接口,也可以代理类。

六、总结

  1. 1、**AOP 是一种思想**,是对某一类事情的集中处理。Spring 框架实现了AOP,称之为 Spring AOP
  2. 2Spring AOP 场景的实现方式有两种:(1)基于注解@Aspect来实现。(2)基于自定义注解来实现,还有一些更原始的方式,比如基于代理、基于 xml 配置的方式,但目标比较少见。
  3. 3Spring AOP 是基于动态代理实现的,有两种方式:(1)基于 JDK 动态代理实现。(2)基于 CGLIB 动态代理实现。运行时使用哪种方式与项目配置的代理对象有关。

本文转载自: https://blog.csdn.net/cool_tao6/article/details/140571214
版权归原作者 tao滔不绝 所有, 如有侵权,请联系我们删除。

“Spring AOP(2)原理(代理模式和源码解析)”的评论:

还没有评论