深入理解spring-AOP注解的底层实现原理
Posted 一个懒惰的程序员
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入理解spring-AOP注解的底层实现原理相关的知识,希望对你有一定的参考价值。
上文简单的介绍了一下基于注解的spring-AOP的使用,没有看过的童鞋可以点击查看,接下来我们就来看看它的底层实现原理是怎样的?
首先我们从开启切面注解@EnableAspectJAutoProxy入手,进去之后可以发现它import()了一个组件AspectJAutoProxyRegistrar如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
/**
* Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
* to standard Java interface-based proxies. The default is {@code false}.
*/
boolean proxyTargetClass() default false;
/**
* Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
* for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
* Off by default, i.e. no guarantees that {@code AopContext} access will work.
* @since 4.3.1
*/
boolean exposeProxy() default false;
}
继续进入AspectJAutoProxyRegistrar我们可以发现它实现了ImportBeanDefinitionRegistrar接口,里边就一个方法registerBeanDefinitions如下:
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
到这里我们可以发现AspectJAutoProxyRegistrar就是自定义封装去注册bean,注意其中的AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry)这行代码,进去我们可以发现注册的是一个AspectJAwareAdvisorAutoProxyCreator如下:
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
一直跟踪AspectJAwareAdvisorAutoProxyCreator进去查看其继承关系如下:
AspectJAwareAdvisorAutoProxyCreator
-->extends AbstractAdvisorAutoProxyCreator
-->extends AbstractAutoProxyCreator
-->extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware
重点看其中标红的两个类,从名字我们可以发现是不是符合xxxBeanPostProcessor和xxxAware,看过小编之前的文章的童鞋应该比较清楚了,没有看过的可以点击以下连接查看:
这边再简单总结下其启动处理流程如下:
1、传入配置类,创建基于注解的ioc容器AnnotationConfigApplicationContext
2、注册配置类,调用refresh方法刷新容器;
3、registerBeanPostProcessors(beanFactory)注册bean的后置处理器来拦截bean的创建;
1)、先获取ioc容器已经定义了的需要创建对象的所有BeanPostProcessor
2)、给容器中加别的BeanPostProcessor
3)、优先注册实现了PriorityOrdered接口的BeanPostProcessor;
4)、再给容器中注册实现了Ordered接口的BeanPostProcessor;
5)、注册没实现优先级接口的BeanPostProcessor;
6)、注册BeanPostProcessor,实际上就是创建对应的bean对象注册到容器中;
1)、创建Bean的实例
2)、populateBean;给bean的各种属性赋值
3)、initializeBean:初始化bean;
1)、invokeAwareMethods()处理Aware接口的方法回调
2)、applyBeanPostProcessorsBeforeInitialization()应用后置处理器的postProcessBeforeInitialization()
3)、invokeInitMethods();执行自定义的初始化方法
4)、applyBeanPostProcessorsAfterInitialization()执行后置处理器的postProcessAfterInitialization();
7)、把BeanPostProcessor注册到BeanFactory中beanFactory.addBeanPostProcessor(postProcessor);
以上就是注册和创建BeanPostProcessor的主要流程自然也就是创建AnnotationAwareAspectJAutoProxyCreator的流程了,接下来再来看看针对AOP切面在AnnotationAwareAspectJAutoProxyCreator中是如何处理的,进入到InstantiationAwareBeanPostProcessor接口的实现postProcessBeforeInstantiation方法如下:
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
Object cacheKey = getCacheKey(beanClass, beanName);
if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
if (beanName != null) {
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
this.targetSourcedBeans.add(beanName);
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
}
return null;
}
找到isInfrastructureClass方法判断当前类是否是基础类Advice,Pointcut,Advisor,AopInfrastructureBean以及是否是切面类(是否包含@Aspect注解),接下来进入getAdvicesAndAdvisorsForBean获取对应的拦截器链如下:
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
/**
* Find all eligible Advisors for auto-proxying this class.
* @param beanClass the clazz to find advisors for
* @param beanName the name of the currently proxied bean
* @return the empty List, not {@code null},
* if there are no pointcuts or interceptors
* @see #findCandidateAdvisors
* @see #sortAdvisors
* @see #extendAdvisors
*/
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = findCandidateAdvisors();
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
最后一步也是最关键的一步创建对应的AOP动态代理createProxy如下:
protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader());
}
继续进入getProxy如下:
public Object getProxy(ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
再一直跟进到createAopProxy的实现如下:
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// 基于cglib的动态代理
return new ObjenesisCglibAopProxy(config);
}
else {
// jdk动态代理
return new JdkDynamicAopProxy(config);
}
}
发现没spring会根据对应的判断采用不同的动态代理的实现,可以是cglib对应的实现也可以基于jdk自己的动态代理实现,有关动态代理的实现原理可以查看
继续进入到CglibAopProxy的动态代理类中的内部静态类的intercept方法如下:
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Class<?> targetClass = null;
Object target = null;
try {
// 省略部分代码....
// 取将要执行的目标方法拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// Check whether we only have one InvokerInterceptor: that is,
// no real advice, but just reflective invocation of the target.
// 如果没有拦截器链则直接执行目标方法
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
// We can skip creating a MethodInvocation: just invoke the target directly.
// Note that the final invoker must be an InvokerInterceptor, so we know
// it does nothing but a reflective operation on the target, and no hot
// swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
else {
// We need to create a method invocation...
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null) {
releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
根据ProxyFactory对象获取将要执行的目标方法拦截器链List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice,再遍历获取到的拦截器链执行拦截方法如下:
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
好了,到此springAOP的实现原理到这里就全部介绍完了,对springAOP具体实现机制感兴趣的同学建议根据这个流程去看一遍,下边再稍微简单总结下AOP分析的大致流程如下:
1)、 @EnableAspectJAutoProxy 开启AOP功能
2)、 @EnableAspectJAutoProxy 往容器中注册一个组件 AnnotationAwareAspectJAutoProxyCreator
3)、AnnotationAwareAspectJAutoProxyCreator是一个后置处理器BeanPostProcessor;
4)、容器的创建流程:
1)、registerBeanPostProcessors注册后置处理器,创建AnnotationAwareAspectJAutoProxyCreator对象
2)、finishBeanFactoryInitialization初始化剩下的单实例bean
1)、创建业务逻辑组件和切面组件
2)、AnnotationAwareAspectJAutoProxyCreator拦截组件的创建过程
3)、组件创建完之后,判断组件是否需要增强
如果是:则把切面的通知方法包装成增强器(Advisor),再给业务组件创建一个代理对象(cglib);
5)、执行目标方法
1)、代理对象执行目标方法
2)、CglibAopProxy.intercept();
1)、得到目标方法的拦截器链(增强器包装成拦截器MethodInterceptor)
2)、利用拦截器的链式机制,依次进入每一个拦截器进行执行;
3)、结果:
正常执行:前置通知-》目标方法-》后置通知-》返回通知
出现异常:前置通知-》目标方法-》后置通知-》异常通知
以上是今天文章的所有内容,欢迎大家吐槽
推荐阅读
以上是关于深入理解spring-AOP注解的底层实现原理的主要内容,如果未能解决你的问题,请参考以下文章