Spring AOP 创建代理对象详情
作者: 斜月
1 前言
在这篇文章中中已经讲述了 AOP 的后置处理器和增强信息的获取,在本文中将继续分享 AOP 创建代理对象和上下文相关的内容。
2 创建代理对象
Spring AOP 使用 JDKProxy 和 CGLIB 两种方式来生成代理对象,具体使用哪一种需要根据 AopProxyFactory 接口的 createProxy 方法中的 AdvisedSupport 中的参数进行确定,默认情况下如果目标类是接口,则使用 jdk 动态代理技术,如果是非接口类,则使用 cglib 来生成代理。
在获取了所有对应 bean 的增强器之后,便可以进行代理的创建了,createProxy
方法。 对于代理类的创建以及处理,spring 委托给 ProxyFactory
进行处理,此方法主要进行初始化操作,并为代理工作做准备。主要分为以下步骤:
- 1 获取当前代理类的属性。
- 2 添加代理接口,封装
Advisor
并加入ProxyFactory
代理工厂中。 - 3 设置要代理的类,
spring
还添加了customizeProxyFactory
,子类可以在改方法中对ProxyFactory
进行包装。 - 4 进行获取代理类的操作。
3 AOPContext Aop 上下文
在最终的代码调用中,还是 JdkDynamicAopProxy
的 invoke
方法和 CglibAopProxy
的 intercept
方法,以 CglibAopProxy
为例,可以看到 AopContext.setCurrentProxy
调用,将当前的对象设置到上下文中,在最后 finally 代码块中会将当前代理对象移除。
AOPContext
的主要方法如下图所示:
4 AOP 分析汇总
综上的逐步分析,最终总结的调用链路图如下所示,分为注册 Bean, 寻找增强器和创建代理等主要环节:
# 注册 bean invokeBeanFactoryPostProcessors @EnableAspectJAutoProxy AspectJAutoProxyRegistrar.registerBeanDefinitions AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source); AopConfigUtils.registerOrEscalateApcAsRequired # 调用 finishBeanFactoryInitialization AbstractAutoProxyCreator.postProcessAfterInitialization AbstractAutoProxyCreator.wrapIfNecessary AbstractAutoProxyCreator.getAdvicesAndAdvisorsForBean AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean AbstractAdvisorAutoProxyCreator.findEligibleAdvisors AbstractAdvisorAutoProxyCreator.findCandidateAdvisors(); AnnotationAwareAspectJAutoProxyCreator.findCandidateAdvisors BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvisors ReflectiveAspectJAdvisorFactory.getAdvisors ReflectiveAspectJAdvisorFactory.getPointcut 获取切点的注解信息 new InstantiationModelAwarePointcutAdvisorImpl instantiateAdvice ReflectiveAspectJAdvisorFactory.getAdvice 获取 advice switch AspectJAroundAdvice AbstractAspectJAdvice.invokeAdviceMethod AspectJMethodBeforeAdvice AspectJAfterAdvice AspectJAfterReturningAdvice AspectJAfterThrowingAdvice AbstractAdvisorAutoProxyCreator.findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); AbstractAutoProxyCreator.createProxy AbstractAutoProxyCreator.buildAdvisors proxyFactory.getProxy(classLoader) DefaultAopProxyFactory.createAopProxy JdkDynamicAopProxy.getProxy ObjenesisCglibAopProxy.getProxy
5 JDK 动态代理和 CGLIB 的区别与联系
在 Spring 中,如果说 IOC 和 DI 解决了类与类之间的耦合,那么动态代理则是解决了方法与方法,业务方法和切面逻辑之间的耦合。
JDK 动态代理只能对实现了接口类生成代理,而不能针对类进行代理。Cglib 是针对类进行代理,针对指定的类生成子类,并覆盖方法并进行增强,因为采用的是继承方式,所代理的类和方法不能是 final 修饰(final 的类或方法,是无法继承的)。
jdk 动态代理
:创建一个实现 InvocationHandler 接口的拦截器,使用 Proxy.newProxyInstance()
反射机制生成一个代理对象,在具体调用方法之前先调用 InvokeHandler.invoke
来处理。
Cglib 动态代理
:利用 ASM 字节码增强框架,对代理对象生成的 class 文件加载进来,通过修改字节码生成子类进行代理。
jdk 和 cglib 使用方法的区别:
- 1 目标对象如果实现了接口,则默认使用 jdk 动态代理。
- 2 如果目标对象实现了接口,可以强制使用 cglib。
- 3 如果目标对象没有实现接口,则必须使用 cglib, spring 会自动在 jdk 和 cglib 代理之间进行切换。
综上, jdk 代理只能针对实现接口的类生成代理,而不能针对类。cglib 只能针对类进行代理。
6 总结
在本文中主要讲述了后置处理器和 AOP 的实现原理,以及 jdk 动态代理和 cglib 代理之间的区别,主要涉及增强获取和代理类的获取,以及后置处理器的理解。
到此这篇关于Spring AOP 创建代理对象详情的文章就介绍到这了,更多相关Spring AOP 内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!