Spring AOP带你了解整个流程,让面试官只能仰望

一,介绍

在这里插入图片描述
提示:解析

A[“JavaConfig”] --> B[“@EnableAspectJAutoProxy”]: 在Spring配置中,启用AspectJ自动代理功能。这是一个注解,可以轻松地启用AOP功能。
B --> C[“注册AnnotationAwareAspectJAutoProxyCreator”]: Spring AOP注册一个AnnotationAwareAspectJAutoProxyCreator bean,它负责根据切点表达式自动为符合条件的bean创建代理。
C --> D[“BeanPostProcessor”]: 在Spring AOP中,BeanPostProcessor接口用于自定义在实例化、配置、初始化等阶段对bean的处理逻辑。Spring AOP会为所有bean注册一个实现了BeanPostProcessor接口的bean。
D --> E[“解析切面”]: BeanPostProcessor在bean初始化后,会解析切面。切面是一个包含通知和切点对象的对象。
E --> F[“解析通知和切点”]: 解析切面后,会解析通知和切点。通知是切面中的方法,切点是这些方法应该被应用到哪些调用的表达式。
F --> G[“缓存Advisor”]: 将解析得到的通知和切点缓存为Advisor对象。Advisor是切面的一种表示形式,它包含了通知和切点信息。
G --> H[“创建动态代理”]: 根据Advisor对象创建动态代理。动态代理是一种运行时生成的类,它实现了目标bean的接口,并将调用转发给目标bean。
H --> I[“判断Bean是否被切点匹配”]: 判断当前bean是否与切点表达式匹配。如果匹配,则进入下一步;否则,直接返回。
I --> J[“是”]: 如果当前bean与切点表达式匹配,则进入下一步。
J --> K[“选择代理创建方式”]: 选择动态代理的创建方式,可以选择JDK动态代理或CGLIB。JDK动态代理只能代理实现了接口的类,而CGLIB可以代理没有实现接口的类。
K --> L[“JDK动态代理或CGLIB”]: 根据上一步的选择,创建代理对象。如果选择了JDK动态代理,则获取目标bean的接口并使用Proxy.newProxyInstance方法创建代理对象;如果选择了CGLIB,则获取目标bean的类并使用CGLIB.Enhancer创建代理对象。
L --> M[“创建代理对象”]: 创建完代理对象后,进入下一步。
M --> V[“调用方法”]: 调用代理对象的方法。如果该方法被增强(即该方法被包含在通知链中),则进入下一步;否则,直接返回。
V --> W[“判断方法是否增强方法”]: 判断上一步调用的方法是否被增强。如果是,进入下一步;否则,根据实际情况进入17或18步。
W --> X[“是”]: 如果该方法被增强,则进入下一步。
X --> Y[“执行通知链”]: 执行通知链中的所有通知方法。这些通知方法会对目标bean的调用进行增强,例如记录日志、性能监控等。
Y --> Z[“调用链中的通知方法”]: 调用链中的第一个通知方法。这个方法会对目标bean的调用进行增强。然后依次调用链中的其他通知方法,直到最后一个通知方法执行完毕。
Z --> AA[“执行目标方法”]: 执行目标方法。这是原始的目标bean的方法调用,没有被增强过。

二,什么是JDK动态代理以及CGLIB代理

提示:JDK动态代理和CGLIB代理都是Java中的动态代理技术,它们在实现方式上有所不同。

JDK动态代理是基于Java反射机制的一种动态代理技术。它要求被代理的目标类必须实现至少一个接口,通过实现InvocationHandler接口来提供具体的代理逻辑。在代理类中,通过调用被代理接口的invoke方法来将方法调用转发给InvocationHandler进行处理。这种方式的优点是代理类与目标类之间解耦,但是要求目标类必须实现接口。

JDK动态代理的具体实现步骤如下:

定义一个接口,并让目标类实现该接口。
实现InvocationHandler接口,提供具体的代理逻辑。
在InvocationHandler实现类中,重写invoke方法,实现在代理类中将方法调用转发给目标类,并将目标类的返回值返回给调用者。
创建代理类实例,并将InvocationHandler实现类的实例作为参数传递给Proxy.newProxyInstance方法,创建代理对象。
通过代理对象调用目标类的方法时,实际上会调用InvocationHandler中的invoke方法进行处理。
CGLIB代理是一种基于CGLIB库的动态代理技术,它通过继承目标类来实现代理,不需要目标类实现接口。CGLIB代理通过生成一个继承目标类的子类来覆盖目标类的方法,并在覆盖的方法中提供代理逻辑。这种方式的优点是不需要修改目标类的代码,但是继承方式会导致代码的侵入性较高。

CGLIB代理的具体实现步骤如下:

定义一个继承自目标类的子类,并重写目标类的方法。
在重写的方法中提供代理逻辑,并调用目标类的方法。
创建子类的实例作为代理对象,并通过该对象调用目标类的方法时,实际上会调用子类重写的方法进行处理。
需要注意的是,在使用CGLIB代理时,需要注意目标类是否被final修饰,因为final修饰的类无法被继承。此外,还需要注意类加载器和字节码生成的问题,因为CGLIB库会根据目标类的字节码生成代理类的字节码。

在Spring框架中,默认情况下会使用JDK动态代理来实现AOP切面。如果目标类没有实现任何接口,Spring会尝试使用CGLIB代理来实现AOP切面。需要注意的是,在使用CGLIB代理时,需要注意目标类是否被final修饰。

三,源码流程图

提示:Java动态代理的源码流程图可以大致分为以下几个步骤:

创建InvocationHandler实例:该实例用于处理代理对象上的方法调用。
创建代理对象:通过Proxy类的静态方法newProxyInstance()创建代理对象,该方法需要传入三个参数:类加载器、代理类实现的接口列表和InvocationHandler实例。
调用代理对象的方法:当代理对象的方法被调用时,实际上会调用InvocationHandler实例的invoke()方法。
invoke()方法中处理方法调用:在invoke()方法中,可以进行方法调用的前后处理,例如记录日志、权限验证等。然后通过反射机制调用目标对象上的对应方法,并返回结果。
下面是一个简单的Java动态代理的源码流程图示例:

创建目标对象实例。
创建InvocationHandler实例,并将目标对象实例作为构造参数传入。
通过Proxy.newProxyInstance()方法创建代理对象,传入类加载器、目标对象实现的接口列表和InvocationHandler实例。
调用代理对象的方法,实际上会调用InvocationHandler实例的invoke()方法。
在invoke()方法中,通过反射机制获取目标对象上的对应方法,并记录日志或进行其他处理。
调用目标对象上的对应方法,并返回结果。
请注意,上述流程仅供参考,具体实现可能会因为不同的场景而有所不同。另外,流程图的具体表现形式可能因为文本限制而不太直观,可以结合代码和调试工具进行更深入的理解。

Java动态代理的源码实现涉及到Java反射机制和字节码技术,如果对这方面不太熟悉,建议先学习一下相关知识。`

创建InvocationHandler实例:该实例用于处理代理对象上的方法调用。
创建代理对象:通过Proxy类的静态方法newProxyInstance()创建代理对象,该方法需要传入三个参数:类加载器、代理类实现的接口列表和InvocationHandler实例。
调用代理对象的方法:当代理对象的方法被调用时,实际上会调用InvocationHandler实例的invoke()方法。
invoke()方法中处理方法调用:在invoke()方法中,可以进行方法调用的前后处理,例如记录日志、权限验证等。然后通过反射机制调用目标对象上的对应方法,并返回结果。

下面是一个简单的Java动态代理的介绍:

创建目标对象实例。
创建InvocationHandler实例,并将目标对象实例作为构造参数传入。
通过Proxy.newProxyInstance()方法创建代理对象,传入类加载器、目标对象实现的接口列表和InvocationHandler实例。
调用代理对象的方法,实际上会调用InvocationHandler实例的invoke()方法。
在invoke()方法中,通过反射机制获取目标对象上的对应方法,并记录日志或进行其他处理。
调用目标对象上的对应方法,并返回结果。
请注意,上述流程仅供参考,具体实现可能会因为不同的场景而有所不同。另外,流程图的具体表现形式可能因为文本限制而不太直观,可以结合代码和调试工具进行更深入的理解。
Java动态代理是一种在运行时创建代理类的技术,通过实现InvocationHandler接口来提供具体的代理逻辑。它适用于对实现了接口的类进行代理,也可以通过继承目标类的方式对没有实现接口的类进行代理。与CGLIB代理相比,JDK动态代理更加灵活和轻量级,但是要求目标类必须实现接口。在Spring框架中,JDK动态代理是默认的代理方式。
Java动态代理的源码实现涉及到Java反射机制和字节码技术,如果对这方面不太熟悉,建议先学习一下相关知识。

小结

Java动态代理是一种在运行时创建代理类的技术,通过实现InvocationHandler接口来提供具体的代理逻辑。它适用于对实现了接口的类进行代理,也可以通过继承目标类的方式对没有实现接口的类进行代理。与CGLIB代理相比,JDK动态代理更加灵活和轻量级,但是要求目标类必须实现接口。在Spring框架中,JDK动态代理是默认的代理方式。

猜你喜欢

转载自blog.csdn.net/qq_49841284/article/details/134865386
今日推荐