Spring AOP
斜月 人气:01 前言
在这篇文章中中已经讲述了 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 代理之间的区别,主要涉及增强获取和代理类的获取,以及后置处理器的理解。
加载全部内容