Spring之AOP源码(二)
书接上文
文章目录
- 一、简介
- 1. 前文回顾
- 2. 知识点补充
- 二、ProxyFactory源码分析
- 1. ProxyFactory
- 2. JdkDynamicAopProxy
- 3. ObjenesisCglibAopProxy
- 三、 Spring AOP源码分析
一、简介
1. 前文回顾
前面我们已经介绍了AOP的基本使用方法以及基本原理,但是还没有涉及源码层面,这篇文章就深度分析一下SpringAOP的底层源码。
2. 知识点补充
- TargetSource
在我们日常的AOP中,被代理对象就是Bean对象,是由BeanFactory给我们创建出来的,但是 Spring AOP中提供了TargetSource机制,可以让我们用来自定义逻辑来创建被代理对象。让我们通过一个简单的案例来说明如何使用 TargetSource。假设我们有一个服务类 UserService,它负责处理用户的业务逻辑,而我们希望在不同的场景下使用不同的实例。
定义目标类:
@Component
public class UserService {public void performAction() {System.out.println("Performing action in UserService");}
}
**自定义 TargetSource:**
@Component
public class CustomTargetSource implements TargetSource {@Overridepublic Class<?> getTargetClass() {return UserService.class;}@Overridepublic boolean isStatic() {return false;}@Overridepublic Object getTarget() throws Exception {// 在此处根据业务逻辑返回不同的目标对象实例// 这里简单地返回一个新的 UserService 实例return new UserService();}@Overridepublic void releaseTarget(Object target) throws Exception {// 可以在这里进行一些资源的释放操作}
}
配置切面:
@Aspect
@Component
public class CustomAspect {@Autowiredprivate CustomTargetSource customTargetSource;@Before("execution(* com.zhouyu.service.UserService.*(..))")public void beforeUserServiceMethod() throws Exception {// 在方法执行前,使用 TargetSource 切换目标对象Object target = customTargetSource.getTarget();// 执行你的逻辑}
}
@Lazy
注解生成代理对象的时候,底层就使用到了TargetSource
protected Object buildLazyResolutionProxy(final DependencyDescriptor descriptor, final @Nullable String beanName) {BeanFactory beanFactory = getBeanFactory();Assert.state(beanFactory instanceof DefaultListableBeanFactory,"BeanFactory needs to be a DefaultListableBeanFactory");final DefaultListableBeanFactory dlbf = (DefaultListableBeanFactory) beanFactory;TargetSource ts = new TargetSource() {@Overridepublic Class<?> getTargetClass() {return descriptor.getDependencyType();}@Overridepublic boolean isStatic() {return false;}@Overridepublic Object getTarget() {Set<String> autowiredBeanNames = (beanName != null ? new LinkedHashSet<>(1) : null);Object target = dlbf.doResolveDependency(descriptor, beanName, autowiredBeanNames, null);if (target == null) {Class<?> type = getTargetClass();if (Map.class == type) {return Collections.emptyMap();}else if (List.class == type) {return Collections.emptyList();}else if (Set.class == type || Collection.class == type) {return Collections.emptySet();}throw new NoSuchBeanDefinitionException(descriptor.getResolvableType(),"Optional dependency not present for lazy injection point");}if (autowiredBeanNames != null) {for (String autowiredBeanName : autowiredBeanNames) {if (dlbf.containsBean(autowiredBeanName)) {dlbf.registerDependentBean(autowiredBeanName, beanName);}}}return target;}@Overridepublic void releaseTarget(Object target) {}};
二、ProxyFactory源码分析
1. ProxyFactory
前面说过这个类是Spring底层对JDK以及Cglib动态代理的底层封装,下面我们分析一下这个类底层是怎么做的。
public static void main(String[] args) {UserService target = new UserService();//创建代理工厂ProxyFactory proxyFactory=new ProxyFactory();//设置代理对象proxyFactory.setTarget(target);//设置代理逻辑proxyFactory.addAdvice(new MethodBeforeAdvice() {@Overridepublic void before(Method method, Object[] args, Object target) throws Throwable {System.out.println("before");}});//返回代理对象UserService proxy = (UserService) proxyFactory.getProxy();proxy.test();}
上面代码是我前面给出的一个案例,其中UserService proxy = (UserService) proxyFactory.getProxy();
就返回了一个代理对象。进入proxyFactory.getProxy
方法。
public Object getProxy() {return createAopProxy().getProxy();}
createAopProxy()
就是用来创建AOP代理的,进入该方法。
protected final synchronized AopProxy createAopProxy() {if (!this.active) {activate();}// 默认为DefaultAopProxyFactoryreturn getAopProxyFactory().createAopProxy(this);}
然后调用createAopProxy
方法。
public interface AopProxyFactory {AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException;
}
我们看AopProxyFactory
的默认实现类DefaultAopProxyFactory
是怎么实现该方法的。
@Overridepublic AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {// 如果ProxyFactory的isOptimize为true,Spring认为cglib比jdk动态代理要快// 或者isProxyTargetClass为true,// 或者被代理对象没有实现接口,// 或者只实现了SpringProxy这个接口// 那么则利用Cglib进行动态代理,但如果被代理类是接口,或者被代理类已经是进行过JDK动态代理而生成的代理类了则只能进行JDK动态代理// 其他情况都会进行JDK动态代理,比如被代理类实现了除SpringProxy接口之外的其他接口// 是不是在GraalVM虚拟机上运行if (!NativeDetector.inNativeImage() &&(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);}return new ObjenesisCglibAopProxy(config);}else {return new JdkDynamicAopProxy(config);}}
上面代码就是在判断当前到底使用jdk动态代理还是cglib动态代理:
- !NativeDetector.inNativeImage():如果当前的JVM是GraalVM那么就直接使用JDK动态代理
- config.isOptimize():表示你是否需要优化(如果需要优化就会使用cglib),然后config就是ProxyFactory本身
- config.isProxyTargetClass():表示代理的目标类是否时接口
- hasNoUserSuppliedProxyInterfaces(config):判断ProxyFactory是否提供了接口
setInterfaces
,如果提供了这个就会返回false - if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) :首先判断被代理的类是否是一个接口,然后判断你现在代理的目标类,是否是jdk产生的代理类
通过上面方法createAopProxy()
就返回了JdkDynamicAopProxy
和ObjenesisCglibAopProxy
这两个对象其中之一。然后,回到getProxy
方法,它就会调用createAopProxy().getProxy();
去生成正在的代理对象。
2. JdkDynamicAopProxy
通过上面代码如果我们最后决定使用的代理类是JdkDynamicAopProxy
,那么就会由这个类生产代理对象。首先我们看看JDK是如何生成我们的代理对象的,关键是getProxy
方法。
@Overridepublic Object getProxy() {return getProxy(ClassUtils.getDefaultClassLoader());}@Overridepublic Object getProxy(@Nullable ClassLoader classLoader) {if (logger.isTraceEnabled()) {logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());}// this实现了InvocationHandlerreturn Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);}
很简单就是使用newProxyInstance
创建了一个代理对象,this就实现了InvocationHandler
。当我们执行代理对象的指定方法时,就会进入invoke方法,我们仔细分析一下这个方法底层:
@Override@Nullablepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object oldProxy = null;boolean setProxyContext = false;// 拿到被代理对象(targetSource) TargetSource targetSource = this.advised.targetSource;Object target = null;try {// 如果接口中没有定义equals()方法,那么则直接调用,不走代理if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {// The target does not implement the equals(Object) method itself.return equals(args[0]);}else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {// The target does not implement the hashCode() method itself.return hashCode();}else if (method.getDeclaringClass() == DecoratingProxy.class) {// There is only getDecoratedClass() declared -> dispatch to proxy config.// 得到代理对象的类型,而不是所实现的接口return AopProxyUtils.ultimateTargetClass(this.advised);}else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&method.getDeclaringClass().isAssignableFrom(Advised.class)) {// Service invocations on ProxyConfig with the proxy config...// 也是直接调用Advised接口中的方法,不走代理逻辑// 其实就是利用代理对象获取ProxyFactory中的信息return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);}Object retVal;// 如果ProxyFactory的exposeProxy为true,则将代理对象设置到currentProxy这个ThreadLocal中去,这样整个线程的执行过程中我们都可以拿到这个代理对象if (this.advised.exposeProxy) {// Make invocation available if necessary.oldProxy = AopContext.setCurrentProxy(proxy);setProxyContext = true;}// Get as late as possible to minimize the time we "own" the target,// in case it comes from a pool.// 拿到真正的目标代理类target = targetSource.getTarget();Class<?> targetClass = (target != null ? target.getClass() : null);// Get the interception chain for this method.// 代理对象在执行某个方法时,根据方法筛选出匹配的Advisor,并适配成InterceptorList<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);// Check whether we have any advice. If we don't, we can fallback on direct// reflective invocation of the target, and avoid creating a MethodInvocation.if (chain.isEmpty()) {// 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.// 如果没有Advice,则直接调用对应方法Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);}else {// We need to create a method invocation...MethodInvocation invocation =new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);// Proceed to the joinpoint through the interceptor chain.retVal = invocation.proceed();}// Massage return value if necessary.Class<?> returnType = method.getReturnType();if (retVal != null && retVal == target &&returnType != Object.class && returnType.isInstance(proxy) &&!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {// Special case: it returned "this" and the return type of the method// is type-compatible. Note that we can't help if the target sets// a reference to itself in another returned object.retVal = proxy;}else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {throw new AopInvocationException("Null return value from advice does not match primitive return type for: " + method);}return retVal;}finally {if (target != null && !targetSource.isStatic()) {// Must have come from TargetSource.targetSource.releaseTarget(target);}if (setProxyContext) {// Restore old proxy.AopContext.setCurrentProxy(oldProxy);}}}
我们知道在AOP中,我们执行指定方法时,这个方法可能会添加多个Advisor,组成一条链,在执行该方法的实际逻辑之前,首先需要执行完所有的Advisor逻辑。而生成这个链(本质上就是list集合)就是下面的代码:
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {// 代理对象在执行某个方法时,会根据当前ProxyFactory中所设置的Advisor根据当前Method再次进行过滤MethodCacheKey cacheKey = new MethodCacheKey(method);// 注意这个List,表示的就是Advice链List<Object> cached = this.methodCache.get(cacheKey);if (cached == null) {cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass);this.methodCache.put(cacheKey, cached);}return cached;}
关键就是调用了getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass);
,这里有一个点就是前面我们使用到的所有Advice,不管是前置通知还是后置通知或者是环绕通知,它们其实类时本质上都是MethodInterceptor
类型。
@Overridepublic List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, @Nullable Class<?> targetClass) {// This is somewhat tricky... We have to process introductions first,// but we need to preserve order in the ultimate list.AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();// 从ProxyFactory中拿到所设置的Advice(添加时被封装成了DefaultPointcutAdvisor)// 添加的时候会控制顺序//取到当前所有的Advisor(切点+advice)//我们在使用porxyFacoty添加advice时会在底层转换为Advisor对象,切点默认是所有方法匹配Advisor[] advisors = config.getAdvisors();List<Object> interceptorList = new ArrayList<>(advisors.length);Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());Boolean hasIntroductions = null;//遍历当前proxyFactory所有的Advisorfor (Advisor advisor : advisors) {if (advisor instanceof PointcutAdvisor) {// Add it conditionally.PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;// 先匹配类if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {// 再匹配方法MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();boolean match;if (mm instanceof IntroductionAwareMethodMatcher) {if (hasIntroductions == null) {hasIntroductions = hasMatchingIntroductions(advisors, actualClass);}match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);}else {match = mm.matches(method, actualClass);}if (match) {// 如果匹配则将Advisor封装成为Interceptor,当前Advisor中的Advice可能即是MethodBeforeAdvice,也是ThrowsAdviceMethodInterceptor[] interceptors = registry.getInterceptors(advisor);if (mm.isRuntime()) {// Creating a new object instance in the getInterceptors() method// isn't a problem as we normally cache created chains.for (MethodInterceptor interceptor : interceptors) {interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));}}else {interceptorList.addAll(Arrays.asList(interceptors));}}// 最终,interceptorList中存储的是当前正在执行的Method所匹配的MethodInterceptor,可能动态的,也可能是非动态的,// 找到Method所匹配的MethodInterceptor后,就会开始调用这些MethodInterceptor,如果是动态的,会额外进行方法参数的匹配}}else if (advisor instanceof IntroductionAdvisor) {IntroductionAdvisor ia = (IntroductionAdvisor) advisor;if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {Interceptor[] interceptors = registry.getInterceptors(advisor);interceptorList.addAll(Arrays.asList(interceptors));}}else {// 将Advisor封装成为InterceptorInterceptor[] interceptors = registry.getInterceptors(advisor);interceptorList.addAll(Arrays.asList(interceptors));}}return interceptorList;}
首先我们看下面这句代码
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
上面这句代码关键是通过pointcutAdvisor.getPointcut()
获得当前的切点,然后调用切点的getClassFilter()
获得要拦截的目标类,然后判断是否和当前类actualClass
匹配,一句话说就是上面if就是判断类型匹配的。如果类型匹配后就会开始匹配方法:
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match;
if (mm instanceof IntroductionAwareMethodMatcher) {if (hasIntroductions == null) {hasIntroductions = hasMatchingIntroductions(advisors, actualClass);}match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);}else {match = mm.matches(method, actualClass);}
关键是调用match = mm.matches(method, actualClass);
这句代码判断当前的方法和要拦截的方法是否匹配。如果前面两个条件都符合,就会执行下面的逻辑:
if (match) {// 如果匹配则将Advisor里面的advice封装成为Interceptor,当前Advisor中的Advice可能即是MethodBeforeAdvice,也是ThrowsAdviceMethodInterceptor[] interceptors = registry.getInterceptors(advisor);//如果方法匹配起的isRuntime属性是trueif (mm.isRuntime()) {for (MethodInterceptor interceptor : interceptors) {interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));}}else {interceptorList.addAll(Arrays.asList(interceptors));}
}
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
首先将当前的Advisor转换为一个MethodInterceptor
对象。然后它会判断你是否设置了方法匹配器的isRuntime
是否为true,为true就会对MethodInterceptor
进行二次封装,这么做的目的就是为了处理如果我们调用的目标类的目标方法有参数,我们还要考虑参数匹配的情况,会被封装到InterceptorAndDynamicMethodMatcher
这个MethodInterceptor
对象中。
@Overridepublic MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {List<MethodInterceptor> interceptors = new ArrayList<>(3);//拿到当前advisor的advice对象Advice advice = advisor.getAdvice();//如果当前的advice本来就是MethodInterceptor类型,直接加入数组中if (advice instanceof MethodInterceptor) {interceptors.add((MethodInterceptor) advice);}// 将Advice适配成MethodInterceptorfor (AdvisorAdapter adapter : this.adapters) {if (adapter.supportsAdvice(advice)) {interceptors.add(adapter.getInterceptor(advisor));}}if (interceptors.isEmpty()) {throw new UnknownAdviceTypeException(advisor.getAdvice());}return interceptors.toArray(new MethodInterceptor[0]);}
上面源码其实就是将一个Advisor中的所有Advice封装到MethodInterceptor[]数组中,如果某个Advice类型是MethodInterceptor,那它就可以直接被添加到这个数组中,否则就要通过下面代码进行适配:
for (AdvisorAdapter adapter : this.adapters) {if (adapter.supportsAdvice(advice)) {interceptors.add(adapter.getInterceptor(advisor));}}
private final List<AdvisorAdapter> adapters = new ArrayList<>(3);/*** Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters.*/public DefaultAdvisorAdapterRegistry() {registerAdvisorAdapter(new MethodBeforeAdviceAdapter());registerAdvisorAdapter(new AfterReturningAdviceAdapter());registerAdvisorAdapter(new ThrowsAdviceAdapter());}
可以看出适配器有三种,分别是MethodBeforeAdviceAdapter
、AfterReturningAdviceAdapter
和ThrowsAdviceAdapter
,分别对应前面说到的前置、后置和异常通知。然后调用adapter.supportsAdvice(advice)
,使用适配器supportsAdvice
,判断当前的Advice是否适配。
可以看出每个适配器都实现了该方法,我们随便拿出其中一个,看看是如何适配的。
@Overridepublic boolean supportsAdvice(Advice advice) {return (advice instanceof AfterReturningAdvice);}
可以发现直接就是instanceof
进行类型判断。进行类型判断后,如果符合,现在就是需要将当前的Advice类型转换为MethodInterceptor
类型,这个同样是适配器完成的adapter.getInterceptor(advisor)
:
@Overridepublic MethodInterceptor getInterceptor(Advisor advisor) {AfterReturningAdvice advice = (AfterReturningAdvice) advisor.getAdvice();return new AfterReturningAdviceInterceptor(advice);}
我们知道不同的Advice执行顺序不同的,而且前面反复强调Advice最后都会转换为MethodInterceptor
对象,然后最后通过这个对象调用相应的通知方法。比方说上面的AfterReturningAdviceInterceptor
就是一个MethodInterceptor
对象,我们看看它底层是如何封装Advice的。
public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {private final AfterReturningAdvice advice;public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) {Assert.notNull(advice, "Advice must not be null");this.advice = advice;}@Override@Nullablepublic Object invoke(MethodInvocation mi) throws Throwable {Object retVal = mi.proceed();this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());return retVal;}}
关键是invoke函数,Object retVal = mi.proceed();
这个就执行了代理目标的实际方法,advice.afterReturning(
这个就是执行了代理逻辑。这就是MethodInterceptor
最核心的逻辑。到此MethodInterceptor
就封装完毕了。回到前面的invoke
方法。我们获得Advisor链之后就会执行下面的逻辑:
if (chain.isEmpty()) {// 如果没有Advice,则直接调用对应方法Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
上面代码的意思是如果我们没有加入任何Advisor,那么就会直接调用目标类的目标方法逻辑。否则就会执行下面的代码:
else {// We need to create a method invocation...MethodInvocation invocation =new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);// Proceed to the joinpoint through the interceptor chain.retVal = invocation.proceed();
}
上面代码首先将MethodInterceptor
数组封装为一个MethodInvocation
对象,然后调用invocation.proceed
,开始执行MethodInterceptor
底层真正的逻辑。
@Override@Nullablepublic Object proceed() throws Throwable {// We start with an index of -1 and increment early.// currentInterceptorIndex初始值为-1,每调用一个interceptor就会加1// 当调用完了最后一个interceptor后就会执行被代理方法if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {return invokeJoinpoint();}// currentInterceptorIndex初始值为-1Object interceptorOrInterceptionAdvice =this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);// 当前interceptor是InterceptorAndDynamicMethodMatcher,则先进行匹配,匹配成功后再调用该interceptor// 如果没有匹配则递归调用proceed()方法,调用下一个interceptorif (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {// Evaluate dynamic method matcher here: static part will already have// been evaluated and found to match.InterceptorAndDynamicMethodMatcher dm =(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());// 动态匹配,根据方法参数匹配if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {return dm.interceptor.invoke(this);}else {// Dynamic matching failed.// Skip this interceptor and invoke the next in the chain.// 不匹配则执行下一个MethodInterceptorreturn proceed();}}else {// It's an interceptor, so we just invoke it: The pointcut will have// been evaluated statically before this object was constructed.// 直接调用MethodInterceptor,传入this,在内部会再次调用proceed()方法进行递归// 比如MethodBeforeAdviceInterceptorreturn ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);}}
我们先看下面代码:
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {return invokeJoinpoint();}
this.currentInterceptorIndex
是ReflectiveMethodInvocation
类的一个属性,默认值是-1,his.interceptorsAndDynamicMethodMatchers
也是该类的一个属性,在构造ReflectiveMethodInvocation
对象时会将我们前面照到的所有MethodInterceptor
赋值给这个属性。这里我们先不说这个if判断的作用,先往后执行代码。
Object interceptorOrInterceptionAdvice =this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
上面代码就是取出下一个MethodInterceptor
。然后继续看后面代码
// 当前interceptor是InterceptorAndDynamicMethodMatcher,则先进行匹配,匹配成功后再调用该interceptor// 如果没有匹配则递归调用proceed()方法,调用下一个interceptorif (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {// Evaluate dynamic method matcher here: static part will already have// been evaluated and found to match.InterceptorAndDynamicMethodMatcher dm =(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());// 动态匹配,根据方法参数匹配if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {return dm.interceptor.invoke(this);}else {// Dynamic matching failed.// Skip this interceptor and invoke the next in the chain.// 不匹配则执行下一个MethodInterceptorreturn proceed();}}else {// It's an interceptor, so we just invoke it: The pointcut will have// been evaluated statically before this object was constructed.// 直接调用MethodInterceptor,传入this,在内部会再次调用proceed()方法进行递归// 比如MethodBeforeAdviceInterceptorreturn ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);}
如果当前的MethodInterceptor
是InterceptorAndDynamicMethodMatcher
类型,它需要进行参数匹配。如果不是该类型直接调用该MethodInterceptor
的invoke方法。
@Override@Nullablepublic Object invoke(MethodInvocation mi) throws Throwable {Object retVal = mi.proceed();this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());return retVal;}
然后Object retVal = mi.proceed();
又调用了proceed方法,就开始执行下一个MethodInterceptor
(有点套娃的意思),直到所有的MethodInterceptor
执行完后,就回到第一个if判断了。
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {return invokeJoinpoint();}
现在进入invokeJoinpoint
方法。
@Nullableprotected Object invokeJoinpoint() throws Throwable {return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);}
@Nullablepublic static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args)throws Throwable {// Use reflection to invoke the method.try {ReflectionUtils.makeAccessible(method);// 执行普通对象的方法,注意和@Configuration产生的代理对象的逻辑区别return method.invoke(target, args);}catch (InvocationTargetException ex) {// Invoked method threw a checked exception.// We must rethrow it. The client won't see the interceptor.throw ex.getTargetException();}catch (IllegalArgumentException ex) {throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +method + "] on target [" + target + "]", ex);}catch (IllegalAccessException ex) {throw new AopInvocationException("Could not access method [" + method + "]", ex);}}
关键就是这句代码return method.invoke(target, args)
执行了被代理对象的指定方法。上面就是Spring AOP代理逻辑的执行过程。
3. ObjenesisCglibAopProxy
前面分析了JDK的动态代理,Cglib动态代理其实流程和这个差不多,我们简单的过一下。首先进入getProxy
源码
@Overridepublic Object getProxy(@Nullable ClassLoader classLoader) {if (logger.isTraceEnabled()) {logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());}try {// 被代理的类Class<?> rootClass = this.advised.getTargetClass();Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");Class<?> proxySuperClass = rootClass;// 如果被代理类本身就已经是Cglib所生成的代理类了if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {// 获取真正的被代理类proxySuperClass = rootClass.getSuperclass();// 获取被代理类所实现的接口Class<?>[] additionalInterfaces = rootClass.getInterfaces();for (Class<?> additionalInterface : additionalInterfaces) {this.advised.addInterface(additionalInterface);}}// Validate the class, writing log messages as necessary.validateClassIfNecessary(proxySuperClass, classLoader);//定义增强器Enhancer enhancer = createEnhancer();if (classLoader != null) {//设置类加载器enhancer.setClassLoader(classLoader);if (classLoader instanceof SmartClassLoader &&((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {enhancer.setUseCache(false);}}// 被代理类,代理类的父类enhancer.setSuperclass(proxySuperClass);// 代理类额外要实现的接口enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));// 获取和被代理类所匹配的AdvisorCallback[] callbacks = getCallbacks(rootClass);Class<?>[] types = new Class<?>[callbacks.length];for (int x = 0; x < types.length; x++) {types[x] = callbacks[x].getClass();}// fixedInterceptorMap only populated at this point, after getCallbacks call aboveenhancer.setCallbackFilter(new ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));enhancer.setCallbackTypes(types);// Generate the proxy class and create a proxy instance.return createProxyClassAndInstance(enhancer, callbacks);}catch (CodeGenerationException | IllegalArgumentException ex) {throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +": Common causes of this problem include using a final class or a non-visible class",ex);}catch (Throwable ex) {// TargetSource.getTarget() failedthrow new AopConfigException("Unexpected AOP exception", ex);}}
和jdk动态代理不同,Cglib动态代理所有的Advisro都会放在一个Callback集合中。
Callback[] callbacks = getCallbacks(rootClass);
我们看看Cglib是怎么利用Advisor建立Callback数组的
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {// 取ProxyFactory的属性boolean exposeProxy = this.advised.isExposeProxy();boolean isFrozen = this.advised.isFrozen();boolean isStatic = this.advised.getTargetSource().isStatic();// Choose an "aop" interceptor (used for AOP calls).Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);Callback targetInterceptor;if (exposeProxy) {targetInterceptor = (isStatic ?new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));}else {targetInterceptor = (isStatic ?new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));}// Choose a "direct to target" dispatcher (used for// unadvised calls to static targets that cannot return this).Callback targetDispatcher = (isStatic ?new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());Callback[] mainCallbacks = new Callback[] {aopInterceptor, // for normal advice,执行Interceptor链targetInterceptor, // invoke target without considering advice, if optimized 将代理对象设置到ThreadLocal中,AopContext.setCurrentProxy(proxy)new SerializableNoOp(), // no override for methods mapped to thistargetDispatcher, this.advisedDispatcher,new EqualsInterceptor(this.advised),new HashCodeInterceptor(this.advised)};Callback[] callbacks;if (isStatic && isFrozen) {Method[] methods = rootClass.getMethods();Callback[] fixedCallbacks = new Callback[methods.length];this.fixedInterceptorMap = CollectionUtils.newHashMap(methods.length);// TODO: small memory optimization here (can skip creation for methods with no advice)for (int x = 0; x < methods.length; x++) {Method method = methods[x];List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());this.fixedInterceptorMap.put(method, x);}// Now copy both the callbacks from mainCallbacks// and fixedCallbacks into the callbacks array.callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);this.fixedInterceptorOffset = mainCallbacks.length;}else {callbacks = mainCallbacks;}return callbacks;}
关键是这句代码Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
。这句代码就创建了一个DynamicAdvisedInterceptor
对象,在使用cglib时这个callbacks数组里面存的对象其实就是MethodInterceptor
,而这个类就是MethodInterceptor
的子类。然后会调用intercept
方法来执行代理逻辑。我们关键看这个intercept
方法。
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {Object oldProxy = null;boolean setProxyContext = false;Object target = null;TargetSource targetSource = this.advised.getTargetSource();try {//这个和jdk动态代理都在做一件事,观察当前的advisor的exposeProxy是否为true,如果是就设置到ThreadLocal中if (this.advised.exposeProxy) {// Make invocation available if necessary.oldProxy = AopContext.setCurrentProxy(proxy);setProxyContext = true;}// 获取代理类target = targetSource.getTarget();//获取代理类类型Class<?> targetClass = (target != null ? target.getClass() : null);//和jdk一样这里同样是获得一个Advisor执行链List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);Object retVal;if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);retVal = methodProxy.invoke(target, argsToUse);}else {//然后执行proceed方法retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();}retVal = processReturnType(proxy, target, method, retVal);return retVal;}finally {if (target != null && !targetSource.isStatic()) {targetSource.releaseTarget(target);}if (setProxyContext) {// Restore old proxy.AopContext.setCurrentProxy(oldProxy);}}}
分析上面代码我们可以看出,它这里的逻辑其实和jdk动态代理的invoke逻辑是一样的。这里就不详细分析了。
经过前面的分析我们知道了ProxyFactory
底层是如何利用jdk和Cglib生成代理对象,以及执行代理逻辑的。现在我们把视角放大,上面讲的东西和Spring AOP有什么关系呢?下面我们就开始分析Spring AOP源码。
三、 Spring AOP源码分析
首先经过前面的分析,我们知道AOP发生的过程是在bean的生命周期的初始化之后(这里不考虑循环依赖中提前AOP的情况)。所以我们进入doCreateBean
方法。
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {
......
try {// 属性填充populateBean(beanName, mbd, instanceWrapper);// 初始化exposedObject = initializeBean(beanName, exposedObject, mbd);}......
}
exposedObject = initializeBean(beanName, exposedObject, mbd);
这个就是执行Bean的初始化,我们进入initializeBean
方法。
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {invokeAwareMethods(beanName, bean);return null;}, getAccessControlContext());}else {//执行回调方法invokeAwareMethods(beanName, bean);}Object wrappedBean = bean;// 初始化前if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}// 初始化try {invokeInitMethods(beanName, wrappedBean, mbd);}catch (Throwable ex) {throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null),beanName, "Invocation of init method failed", ex);}// 初始化后 AOPif (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean;}
注意上面代码就是一个Bean初始化后要做的事情,关于AOP这块就是在下面这段代码中:
// 初始化后 AOPif (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}@Overridepublic Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)throws BeansException {//拿到当前的beanObject result = existingBean;//获取所有的BeanPostProcessorfor (BeanPostProcessor processor : getBeanPostProcessors()) {//执行BeanPostProcessor的postProcessAfterInitializationObject current = processor.postProcessAfterInitialization(result, beanName);if (current == null) {return result;}result = current;}return result;}
applyBeanPostProcessorsAfterInitialization
方法的逻辑就是,找到所有的BeanPostProcessor然后执行每个BeanPostProcessor的postProcessAfterInitialization
方法来执行初始化后的逻辑。这里我们先要知道AOP就是需要一个特定的BeanPostProcessor
去执行它的postProcessAfterInitialization
方法来实现AOP的。下面我们就来揭开这个特殊的BeanPostProcessor
的面纱。
首先我们知道,要开启AOP我们需要在配置类上加入@EnableAspectJAutoProxy
注解。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {boolean proxyTargetClass() default false;boolean exposeProxy() default false;
}
- proxyTargetClass(): 默认值为 false,表示是否强制使用CGLIB代理方式。如果设置为 true,则表示使用CGLIB代理;否则使用JDK动态代理。
- exposeProxy(): 默认值为 false,表示是否将当前代理对象暴露为ThreadLocal。如果设置为 true,则可以通过AopContext.currentProxy()来获取当前代理对象。
注意这个注解上面导入了@Import(AspectJAutoProxyRegistrar.class)
在分析Spring启动源码的时候,我们分析过这个注解的作用可以起一个导入Bean的作用。这也是EnableAspectJAutoProxy
注解的核心作用。我们就来分析一下这个类。
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {// 注册一个AnnotationAwareAspectJAutoProxyCreator类型的Bean,beanName为AUTO_PROXY_CREATOR_BEAN_NAMEAopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);// 修改AnnotationAwareAspectJAutoProxyCreator中对应的属性AnnotationAttributes enableAspectJAutoProxy =AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);if (enableAspectJAutoProxy != null) {if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);}if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);}}}}
首先这个类实现了ImportBeanDefinitionRegistrar
这个接口,所以这个类在Spring启动过程中会调用registerBeanDefinitions
方法。方法里注册一个AnnotationAwareAspectJAutoProxyCreator
类型的BeanDefinition,beanName为AUTO_PROXY_CREATOR_BEAN_NAME
。这个Bean就是AOP的关键。
//1
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
//2
@Nullablepublic static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);}
//3
@Nullablepublic static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) {return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);}//4
@Nullableprivate static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {Assert.notNull(registry, "BeanDefinitionRegistry must not be null");if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);if (!cls.getName().equals(apcDefinition.getBeanClassName())) {int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());int requiredPriority = findPriorityForClass(cls);if (currentPriority < requiredPriority) {apcDefinition.setBeanClassName(cls.getName());}}return null;}//这里就是注册前面bean得逻辑RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);beanDefinition.setSource(source);beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);return beanDefinition;}
下面我们就开始分析这个核心beanAUTO_PROXY_CREATOR_BEAN_NAME
。
public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {@Nullableprivate List<Pattern> includePatterns;@Nullableprivate AspectJAdvisorFactory aspectJAdvisorFactory;@Nullableprivate BeanFactoryAspectJAdvisorsBuilder aspectJAdvisorsBuilder;public void setIncludePatterns(List<String> patterns) {this.includePatterns = new ArrayList<>(patterns.size());for (String patternText : patterns) {this.includePatterns.add(Pattern.compile(patternText));}}public void setAspectJAdvisorFactory(AspectJAdvisorFactory aspectJAdvisorFactory) {Assert.notNull(aspectJAdvisorFactory, "AspectJAdvisorFactory must not be null");this.aspectJAdvisorFactory = aspectJAdvisorFactory;}@Overrideprotected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {super.initBeanFactory(beanFactory);if (this.aspectJAdvisorFactory == null) {this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);}this.aspectJAdvisorsBuilder =new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);}@Overrideprotected List<Advisor> findCandidateAdvisors() {// Add all the Spring advisors found according to superclass rules.// 先找到所有Advisor类型的Bean对象List<Advisor> advisors = super.findCandidateAdvisors();// Build Advisors for all AspectJ aspects in the bean factory.// 再从所有切面中解析得到Advisor对象if (this.aspectJAdvisorsBuilder != null) {advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());}return advisors;}@Overrideprotected boolean isInfrastructureClass(Class<?> beanClass) {return (super.isInfrastructureClass(beanClass) ||(this.aspectJAdvisorFactory != null && this.aspectJAdvisorFactory.isAspect(beanClass)));}protected boolean isEligibleAspectBean(String beanName) {if (this.includePatterns == null) {return true;}else {for (Pattern pattern : this.includePatterns) {if (pattern.matcher(beanName).matches()) {return true;}}return false;}}private class BeanFactoryAspectJAdvisorsBuilderAdapter extends BeanFactoryAspectJAdvisorsBuilder {public BeanFactoryAspectJAdvisorsBuilderAdapter(ListableBeanFactory beanFactory, AspectJAdvisorFactory advisorFactory) {super(beanFactory, advisorFactory);}@Overrideprotected boolean isEligibleBean(String beanName) {return AnnotationAwareAspectJAutoProxyCreator.this.isEligibleAspectBean(beanName);}}}
我们从这个类开始不断找到它的父类,以及父类的父类,会来到这个类。
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupportimplements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {}
它实现了implements SmartInstantiationAwareBeanPostProcessor
说明,上面注册的那个bean确实是一个BeanPostProcessor。好现在我们知道了这个BeanPostProcessor,现在我们继续回到Bean的生命周期中。
@Overridepublic Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)throws BeansException {//拿到当前的beanObject result = existingBean;//获取所有的BeanPostProcessorfor (BeanPostProcessor processor : getBeanPostProcessors()) {//执行BeanPostProcessor的postProcessAfterInitializationObject current = processor.postProcessAfterInitialization(result, beanName);if (current == null) {return result;}result = current;}return result;}
关键代码就是执行bject current = processor.postProcessAfterInitialization(result, beanName);
。然后上面关于AOP的BeanPostProcessor就会执行下面代码
@Overridepublic Object postProcessAfterInstantiation(@Nullable Object bean, String beanName) {if (bean != null) {Object cacheKey = getCacheKey(bean.getClass(), beanName);if (this.earlyProxyReferences.remove(cacheKey) != bean) {return wrapIfNecessary(bean, beanName, cacheKey);}}return bean;}
然后wrapIfNecessary
就是创建真正的代理对象的逻辑
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {return bean;}// this.advisedBeans表示已经判断过了的bean,false表示此bean不需要进行Aop if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {return bean;}// 当前正在创建的Bean不用进行AOP,比如切面Bean,advisedBeans里面就存储了不需要进行AOP的beanif (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;}// Create proxy if we have advice.// 判断当前bean是否存在匹配的advice,如果存在则要生成一个代理对象// 此处根据类以及类中的方法去匹配到Interceptor(也就是Advice),然后生成代理对象,代理对象在执行的时候,还会根据当前执行的方法去匹配Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);if (specificInterceptors != DO_NOT_PROXY) {// advisedBeans记录了某个Bean已经进行过AOP了this.advisedBeans.put(cacheKey, Boolean.TRUE);Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));this.proxyTypes.put(cacheKey, proxy.getClass());return proxy;}this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;}
上面方法首先会找出不需要进行AOP的bean,如我们的加了Aspectj注解的bean,并加入到this.advisedBeans
这个集合中。我们重点看下面代码:
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
其实上面的代码就是判断当前的bean需不需要进行AOP,相信大家还记得ProxyFactory
的逻辑里面也进行了一次判断。如果要进行AOP,则进入的下面的if判断,否则这几返回bean。
if (specificInterceptors != DO_NOT_PROXY) {// advisedBeans记录了某个Bean已经进行过AOP了this.advisedBeans.put(cacheKey, Boolean.TRUE);Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));this.proxyTypes.put(cacheKey, proxy.getClass());return proxy;}
上面调用了createProxy
来创建代理对象,进入该方法。
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,@Nullable Object[] specificInterceptors, TargetSource targetSource) {if (this.beanFactory instanceof ConfigurableListableBeanFactory) {AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);}//创建一个ProxyFactoryProxyFactory proxyFactory = new ProxyFactory();proxyFactory.copyFrom(this);if (proxyFactory.isProxyTargetClass()) {// Explicit handling of JDK proxy targets (for introduction advice scenarios)if (Proxy.isProxyClass(beanClass)) {// Must allow for introductions; can't just set interfaces to the proxy's interfaces only.for (Class<?> ifc : beanClass.getInterfaces()) {proxyFactory.addInterface(ifc);}}}else {// No proxyTargetClass flag enforced, let's apply our default checks...if (shouldProxyTargetClass(beanClass, beanName)) {proxyFactory.setProxyTargetClass(true);}else {evaluateProxyInterfaces(beanClass, proxyFactory);}}Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);// 在这一步会去判断advisors中是否存在IntroductionAdvisor,如果存在则会把对应的interface添加到proxyFactory中去proxyFactory.addAdvisors(advisors);//设置TargetproxyFactory.setTargetSource(targetSource);customizeProxyFactory(proxyFactory);proxyFactory.setFrozen(this.freezeProxy);if (advisorsPreFiltered()) {proxyFactory.setPreFiltered(true);}// Use original ClassLoader if bean class not locally loaded in overriding class loaderClassLoader classLoader = getProxyClassLoader();if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();}return proxyFactory.getProxy(classLoader);}
看到上面代码我们就会到了ProxyFactory
的逻辑,这里就将SpringAOP和ProxyFactory
联系起来了,后面如何产生代理对象,前面都分析了。proxyFactory.addAdvisors(advisors);
就是添加Advisor,那么这个Advisor哪里来,其实就是参数中的 Object[] specificInterceptors
这个数组,这个数组是由前面调用的getAdvicesAndAdvisorsForBean
方法来的,假如现在BeanPostProcessor处理的bean为Userservice,通过该方法就可以找到所有和UserService有关的Advisor,我们看看这个方法底层是如何找的。
@Override@Nullableprotected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {// 寻找匹配的AdvisorList<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);if (advisors.isEmpty()) {return DO_NOT_PROXY;}return advisors.toArray();}
findEligibleAdvisors
这个是寻找匹配的Advisor的核心方法,我们进入该方法。
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {// 找到所有的AdvisorList<Advisor> candidateAdvisors = findCandidateAdvisors();// 进行筛选List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);extendAdvisors(eligibleAdvisors);// 对Advisor进行排序,按Ordered接口、@Order注解进行排序if (!eligibleAdvisors.isEmpty()) {eligibleAdvisors = sortAdvisors(eligibleAdvisors);}return eligibleAdvisors;}
List<Advisor> candidateAdvisors = findCandidateAdvisors();
就会找到所有的Advisor。
@Overrideprotected List<Advisor> findCandidateAdvisors() {// Add all the Spring advisors found according to superclass rules.// 先找到所有Advisor类型的Bean对象List<Advisor> advisors = super.findCandidateAdvisors();// Build Advisors for all AspectJ aspects in the bean factory.// 再从所有切面中解析得到Advisor对象if (this.aspectJAdvisorsBuilder != null) {advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());}return advisors;}
上面代码首先调用super.findCandidateAdvisors
找到所有Advisor
类型的bean,然后解析加了@AspectJ注解的bean解析出来。
public List<Advisor> buildAspectJAdvisors() {// aspectBeanNames是用来缓存BeanFactory中所存在的切面beanName的,第一次为null,后面就不为null了,不为null表示之前就已经找到过BeanFactory中的切面了List<String> aspectNames = this.aspectBeanNames;if (aspectNames == null) {synchronized (this) {aspectNames = this.aspectBeanNames;if (aspectNames == null) {List<Advisor> advisors = new ArrayList<>();aspectNames = new ArrayList<>();// 把所有beanNames拿出来遍历,判断某个bean的类型是否是AspectString[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);for (String beanName : beanNames) {if (!isEligibleBean(beanName)) {continue;}//获取当前bean的类型Class<?> beanType = this.beanFactory.getType(beanName, false);if (beanType == null) {continue;}//判断当前类型bean上面是否有AspectJ注解if (this.advisorFactory.isAspect(beanType)) {aspectNames.add(beanName);// 切面的注解信息AspectMetadata amd = new AspectMetadata(beanType, beanName);// 如果@Aspect不是perthis、pertarget,那么一个切面只会生成一个对象(单例)// 并且会将该切面中所对应的Advisor对象进行缓存if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {MetadataAwareAspectInstanceFactory factory =new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);// 利用BeanFactoryAspectInstanceFactory来解析Aspect类List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);if (this.beanFactory.isSingleton(beanName)) {// 缓存切面所对应的所有Advisor对象this.advisorsCache.put(beanName, classAdvisors);}else {this.aspectFactoryCache.put(beanName, factory);}advisors.addAll(classAdvisors);}else {// Per target or per this.if (this.beanFactory.isSingleton(beanName)) {throw new IllegalArgumentException("Bean with name '" + beanName +"' is a singleton, but aspect instantiation model is not singleton");}MetadataAwareAspectInstanceFactory factory =new PrototypeAspectInstanceFactory(this.beanFactory, beanName);this.aspectFactoryCache.put(beanName, factory);// 利用PrototypeAspectInstanceFactory来解析Aspect类// PrototypeAspectInstanceFactory的父类为BeanFactoryAspectInstanceFactory// 这两个Factory的区别在于PrototypeAspectInstanceFactory的构造方法中会判断切面Bean是不是原型,除此之外没有其他区别// 所以主要就是BeanFactoryAspectInstanceFactory来负责生成切面实例对象advisors.addAll(this.advisorFactory.getAdvisors(factory));}}}this.aspectBeanNames = aspectNames;return advisors;}}}if (aspectNames.isEmpty()) {return Collections.emptyList();}// 如果切面已经找到过了,那么则遍历每个切面是否缓存了对应的Advisor,如果没有缓存则进行解析得到AdvisorList<Advisor> advisors = new ArrayList<>();for (String aspectName : aspectNames) {List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);if (cachedAdvisors != null) {advisors.addAll(cachedAdvisors);}else {MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);advisors.addAll(this.advisorFactory.getAdvisors(factory));}}return advisors;}
上面的类就是解析加了@Aspectj注解的bean,其实就是解析里面的@Before等注解,然后生成一系列的Advisor对象返回,底层还是很复杂的,这里就不深入分析了。回到wrapIfNecessary
,现在就找到了很多Advisor。
相关文章:

Spring之AOP源码(二)
书接上文 文章目录 一、简介1. 前文回顾2. 知识点补充 二、ProxyFactory源码分析1. ProxyFactory2. JdkDynamicAopProxy3. ObjenesisCglibAopProxy 三、 Spring AOP源码分析 一、简介 1. 前文回顾 前面我们已经介绍了AOP的基本使用方法以及基本原理,但是还没有涉…...
VS code console.log快捷键设置 :console.log(‘n>>>‘,n)
vscode设置log快捷显示: 一、打开 VS Code,并进入菜单栏选择 “文件”(File)-> “首选项”(Preferences)-> “用户代码片段”(User Snippets)。 二、在弹出的下拉菜单中选择 …...

ZooKeeper 简介
1、概念介绍 ZooKeeper 是一个开放源码的分布式应用程序协调服务,为分布式应用提供一致性服务的软件,由雅虎创建,是 Google Chubby 的开源实现,是 Apache 的子项目,之前是 Hadoop 项目的一部分,使用 Java …...

rke2 Online Deploy Rancher v2.8.0 latest (helm 在线部署 rancher v2.8.0)
文章目录 1. 简介2. 预备条件3. 安装 helm4. 安装 cert-manager4.1 yaml 安装4.2 helm 安装 5. 安装 rancher6. 验证7. 界面预览 1. 简介 Rancher 是一个 Kubernetes 管理工具,让你能在任何地方和任何提供商上部署和运行集群。 Rancher 可以创建来自 Kubernetes 托…...
k8s实战从入门到上天系列第一篇:K8s微服务实战内容开篇介绍
前言 我们使用开源ruoyi微服务基本使用,基于基本的微服务实践。我们来讲解k8s的实战内容。 第一章:开源ruoyi微服务简介基本使用 第二章:k8s基本知识回顾、k3s集群搭建和基本使用 第三章:微服务镜像构建 第四章:中间件…...

统一网关 Gateway【微服务】
文章目录 1. 前言2. 搭建网关服务3. 路由断言工厂4. 路由过滤器4.1 普通过滤器4.2 全局过滤器4.3 过滤器执行顺序 5. 跨域问题处理 1. 前言 通过前面的学习我们知道,通过 Feign 就可以向指定的微服务发起 http 请求,完成远程调用。但是这里有一个问题&am…...

【征服redis1】基础数据类型详解和应用案例
博客计划 ,我们从redis开始,主要是因为这一块内容的重要性不亚于数据库,但是很多人往往对redis的问题感到陌生,所以我们先来研究一下。 本篇,我们先看一下redis的基础数据类型详解和应用案例。 1.redis概述 以mysql为…...
【WPF.NET开发】WPF中的XAML资源
本文内容 使用 XAML 中的资源静态和动态资源静态资源动态资源样式、DataTemplate 和隐式键 资源是可以在应用中的不同位置重复使用的对象。 资源的示例包括画笔和样式。 本概述介绍如何使用 Extensible Application Markup Language (XAML) 中的资源。 你还可以使用代码创建和…...
ChatGPT 淘金潮(全)
原文:The ChatGPT GoldRush 译者:飞龙 协议:CC BY-NC-SA 4.0 一、ChatGPT 简介 什么是 ChatGPT? ChatGPT 是由 OpenAI 基于 GPT-4 架构创建的大型语言模型。它旨在理解和回应自然语言文本输入,使得可以与机器进行对话…...

【零基础入门Python数据分析】Anaconda3 JupyterNotebookseaborn版
目录 一、安装环境 python介绍 anaconda介绍 jupyter notebook介绍 anaconda3 环境安装 解决JuPyter500:Internal Server Error问题-CSDN博客 Jupyter notebook快捷键操作大全 二、Python基础入门 数据类型与变量 数据类型 变量及赋值 布尔类型与逻辑运算…...
C++面试:单例模式、工厂模式等简单的设计模式 创建型、结构型、行为型设计模式的应用技巧
理解和能够实现基本的设计模式是非常重要的。这里,我们将探讨两种常见的设计模式:单例模式和工厂模式,并提供一些面试准备的建议。 目录 单例模式 (Singleton Pattern) 工厂模式 (Factory Pattern) 面试准备 1. 理解设计模式的基本概念…...
Oracle JDK 8 中的 computeIfAbsent 方法及实践
Java 8 引入了一系列新特性,其中之一是对 Map 接口的增强,其中包括了 computeIfAbsent 方法。这个方法为处理映射提供了一种便捷而强大的方式,允许在键不存在或对应的值为 null 时,动态计算新的值并将其放入映射。在本篇博客中&am…...

华为设备vlan下配置MSTP,STP选举
核心代码,不同实例,承载不同流量,为每个实例设置一个根网桥达到分流的效果 stp region-config //进入stp区域的设置 region-name R1 //区域命名为R1 instance 1 vlan 10 …...
案例学Python:filter()函数的用法,高级!
大家好,这里是程序员晚枫,又来分享有用的Python知识了。 Python之所以好用,是因为有大量用于科学计算的内置函数和第三方库。用好这些第三方库,可以显著提高我们编程的速度和质量。 今天我们一起来看一下Python中一个重要的内置…...

jmeter--7.BeanShell
目录 1. beanshell常用语法 1.1 log:日志写入 1.2 vars:设置和引用局部变量(同线程组) 1.3 props:设置和引用全局变量(跨线程组) 1.4 prev:获取前一个请求返回的信息 2. beans…...

第 3 场 蓝桥杯小白入门赛 解题报告 | 珂学家 | 单调队列优化的DP + 三指针滑窗
前言 整体评价 T5, T6有点意思,这场小白入门场,好像没真正意义上的签到,整体感觉是这样。 A. 召唤神坤 思路: 前后缀拆解 #include <iostream> #include <algorithm> #include <vector> using namespace std;int main()…...
debian apt 装 mysql8
MySQL :: MySQL 8.0 参考手册 :: 2.5.5 使用来自 Oracle 的 Debian 软件包在 Linux 上安装 MySQL apt install -f lsb-release gnupg wget https://repo.mysql.com//mysql-apt-config_0.8.29-1_all.deb dpkg -i mysql-apt-config…...

LeetCode 每日一题 Day 37-43
终于考完试了,寒假期间将会每天持续更新! 447. 回旋镖的数量(Day 37) 给定平面上 n 对 互不相同 的点 points ,其中 points[i] [xi, yi] 。回旋镖 是由点 (i, j, k) 表示的元组 ,其中 i 和 j 之间的欧式距离和 i 和 k 之间的欧…...

产品百度百科怎么创建?产品如何上百度百科?
百度百科作为一个权威的信息平台,承载着巨大的流量和曝光度。对于一个产品来说,能够在百度百科上拥有一席之地,无疑是一种极高的荣誉,同时也是提升品牌知名度、增加信任度的重要手段。产品百度百科不仅能够详细、全面地介绍产品信…...

Vue keep-alive的使用和原理解析
✨ 专栏介绍 在当今Web开发领域中,构建交互性强、可复用且易于维护的用户界面是至关重要的。而Vue.js作为一款现代化且流行的JavaScript框架,正是为了满足这些需求而诞生。它采用了MVVM架构模式,并通过数据驱动和组件化的方式,使…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...

【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...

汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...

3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...

算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...

push [特殊字符] present
push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...
微服务通信安全:深入解析mTLS的原理与实践
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、引言:微服务时代的通信安全挑战 随着云原生和微服务架构的普及,服务间的通信安全成为系统设计的核心议题。传统的单体架构中&…...
数据库——redis
一、Redis 介绍 1. 概述 Redis(Remote Dictionary Server)是一个开源的、高性能的内存键值数据库系统,具有以下核心特点: 内存存储架构:数据主要存储在内存中,提供微秒级的读写响应 多数据结构支持&…...
Python 高级应用10:在python 大型项目中 FastAPI 和 Django 的相互配合
无论是python,或者java 的大型项目中,都会涉及到 自身平台微服务之间的相互调用,以及和第三发平台的 接口对接,那在python 中是怎么实现的呢? 在 Python Web 开发中,FastAPI 和 Django 是两个重要但定位不…...