在spring中。Aop是其一大特色。要想开启spring的aop功能,可以通过在xml中配置
<aop:aspectj-autoporxy/> |
开启注解,然后定义对应的切面,切点来完成。同样也可以通过@EnableAspectJAutoProxy注解来完成开启。在分析之前我们首先通过一个例子
@Configuration @ComponentScan(basePackages = {"com.test.aop"}) @EnableAspectJAutoProxy public class AopConfig { } |
在com.test.aop包下创建如下两个类
@Component //代表当前是一个切面,spring会解析该注解中的方法进行植入 @Aspect public class LogHandler { /** * 定义一个切入点 * 这代表切入点是名称为saying方法(可以配置包路径,参数等) */ @Pointcut("execution(* *.saying(..))") public void sayings(){} //定义通知,前置通知 @Before("sayings()") public void LogBefore() { System.out.println("Log before method"); } //后置通知 @After("sayings()") public void LogAfter() { System.out.println("Log after method"); } } |
定义一个含有saying方法的bean
@Service public class Business { public void saying(){ System.out.println("saying 方法执行了"); } } |
在调用business.saying的时候会输出如下结果
可以看到已经在方法执行进行切入了,那么我们从源码的角度来分一下。Spring是如何做的。
首先看@EnableAspectJAutoProxy注解做了什么。
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(AspectJAutoProxyRegistrar.class) public @interface EnableAspectJAutoProxy { boolean proxyTargetClass() default false; boolean exposeProxy() default false; } |
还记得我们之前在说通过ConfigurationClassPostProcessor的作用吗。忘记了请查看8_invokeBeanFactoryPostProcessors 在spring进行解析配置类的时候如果发现有@Import或者实现了ImportSelector和importBeanDefinitionRegistrars接口会分别调用对应的方法,将其中的符合的bean注册到spring容器中。
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
/** * Register, escalate, and configure the AspectJ auto proxy creator based on the value * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing * {@code @Configuration} class. */ @Override 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); } } } |
通过源码可以看出它是实现了ImportBeanDefinitionRegistrar接口,所以在ConfigurationClassPostProcessor执行postProcessBeanDefinitionRegistry会调用该方法。
继续分析AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
实际就是向spring注册了一个AnnotationAwareAspectJAutoProxyCreator的bean。然后下面的代码为向该bean的proxyTargetClass进行设置相关的赋值。
下面我看下AnnotionAwareAspectJAutoProxyCreator的继承关系
从图中可以看出实现了SmartInstantionationAwareBeanPostProcessor
前面我们说过,在初始化完成bean后会调用后置处理器的postProcessAfterInstantiation来对相关的类进行处理,那么我们来看下AnnotationAwareAspectJAutoProxyCreator类的源码
@Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean != null) { //先从缓存中获取 Object cacheKey = getCacheKey(bean.getClass(), beanName); //在之前谈到过,为了解决循环依赖问题,会返回一个 //当前bean的ObjectFactory。如果当前bean在提前暴露 //的map中,说明已经有通过ObjectFactory.getObject方式获取 //当前bean的代理类了,于是当前的类创建过程不需要继续返回一个 //相关的代理。如果没有,则对当前类进行封装 if (!this.earlyProxyReferences.contains(cacheKey)) { return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; } |
下面进入wrapIfNecessary方法
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { //已处理过,直接返回 if (beanName != null && this.targetSourcedBeans.contains(beanName)) { return bean; } //当前类不需要增强,这些是在postProcessBeforeInitialization进行初始化 if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } //实现了Advice,PointCut,Advisor, AopInfrastructureBean是基础类,不需要代理 if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; }
//查询当前bean符合的advice。 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); //如果有,则进行创建代理。 if (specificInterceptors != DO_NOT_PROXY) { 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; } |
下面我们分别分析上面的两个动作,一是查找可以适配的增强器,二是生成对应的代理
@Override 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(); } |
进入findEligibleAdvisors
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { //查找所有的增强器 List<Advisor> candidateAdvisors = findCandidateAdvisors(); //获取当前的bean适合的增强器 List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); //添加一个默认的增强DefaultPointcutAdvisor extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { //所有的增强进行排序 eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; } |
进入AnnotationAwareAspectJAutoProxyCreator的findCandidateAdvisors
@Override protected List<Advisor> findCandidateAdvisors() { // 查找实现了所有的advisor接口的bean List<Advisor> advisors = super.findCandidateAdvisors(); //遍历所有的bean,查找声明了Aspect注解,并且进行相关解析 //@Before,@Around,@After advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); return advisors; } |
下面我们分析一下获取到对应的增强器,如何判断当前增强器是否可以使用的
protected List<Advisor> findAdvisorsThatCanApply( List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) { //设置线程相关的变量,当前的线程正在试图增强的bean的名称 ProxyCreationContext.setCurrentProxiedBeanName(beanName); try { //真正进行增强器选择 return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass); } finally { ProxyCreationContext.setCurrentProxiedBeanName(null); } } |
进入AopUtils.findAdvisorThatCanApply函数中
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) { if (candidateAdvisors.isEmpty()) { return candidateAdvisors; } List<Advisor> eligibleAdvisors = new LinkedList<Advisor>(); for (Advisor candidate : candidateAdvisors) { //根据不同的增强器类型来进行不同的判断 if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) { eligibleAdvisors.add(candidate); } } boolean hasIntroductions = !eligibleAdvisors.isEmpty(); for (Advisor candidate : candidateAdvisors) { if (candidate instanceof IntroductionAdvisor) { // already processed continue; } if (canApply(candidate, clazz, hasIntroductions)) { eligibleAdvisors.add(candidate); } } return eligibleAdvisors; } |
实际的判断方法存在于canApply方法中。
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) { if (advisor instanceof IntroductionAdvisor) { return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass); } //通过aop代理实现的增强器是PointcutAdvisor类型 else if (advisor instanceof PointcutAdvisor) { PointcutAdvisor pca = (PointcutAdvisor) advisor; //通过判断当前的类型 //里边的大概逻辑就是通过method找到对应的匹配表达式,验证 //是否能够进行匹配。AspectJExpressionPointcut: () sayings() return canApply(pca.getPointcut(), targetClass, hasIntroductions); } else { // It doesn't have a pointcut so we assume it applies. return true; } } |
下面我们回到之前看下aop代理的实现方式。现在找到对应的增强器。紧接着需要根据增强器生成对应的代理类。
protected Object createProxy( Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) { //根据beanFactory设置exposeTargetClass 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); //控制代理后,该bean是否还允许被修改 proxyFactory.setFrozen(this.freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } //使用工厂创建代理类。 return proxyFactory.getProxy(getProxyClassLoader()); } |
进入ProxyFactory
protected final synchronized AopProxy createAopProxy() { if (!this.active) { activate(); } //获取aopProxyFactory.由于可以采用CGLIB以及JDK自带的代理 //所以需要在这里选择一个方式 return getAopProxyFactory().createAopProxy(this); } |
进入DefaultAopProxyFactory.有以下方法可以看出,如果当前的类有接口,默认使用jdk代理,当然通过更改ProxyTargetClass属性可以让其使用CGLib代理。Jdk动态代理只能针对接口,而CGLIB是通过继承父类实现。
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); } return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } } |
下面首先进入CglibAopProxy的getProxy中.在当前类通过Cglib通用的Enhancer辅助类,进行创建了代理对象,这里我们只要关注的是getCallback函数中加入了一个
DynamicAdvisedInterceptor,在调用该代理对象的方法时会调用该拦截器的intercept方法。
先留个伏笔,看下jdk动态代理返回的对象。
@Override public Object getProxy(ClassLoader classLoader) { if (logger.isDebugEnabled()) { logger.debug("Creating CGLIB proxy: target source is " + 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代理过的。其实就是判断是否包含$$。 //如果是cglib代理的,需要把当前的代理接口拿出来 if (ClassUtils.isCglibProxyClass(rootClass)) { proxySuperClass = rootClass.getSuperclass(); Class<?>[] additionalInterfaces = rootClass.getInterfaces(); for (Class<?> additionalInterface : additionalInterfaces) { this.advised.addInterface(additionalInterface); } }
// 验证。写入相关日志,是否有static方法以及final方法 validateClassIfNecessary(proxySuperClass, classLoader);
// 创建一个Enhancer 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 ClassLoaderAwareUndeclaredThrowableStrategy(classLoader)); //设置拦截器 //当前会注入很多的拦截器DynamicAdvisedInterceptor为其中之一 // Callback[] 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 above enhancer.setCallbackFilter(new ProxyCallbackFilter( this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset)); enhancer.setCallbackTypes(types);
//生成代理类 return createProxyClassAndInstance(enhancer, callbacks); } catch (CodeGenerationException ex) { throw new AopConfigException("Could not generate CGLIB subclass of class [" + this.advised.getTargetClass() + "]: " + "Common causes of this problem include using a final class or a non-visible class", ex); } catch (IllegalArgumentException ex) { throw new AopConfigException("Could not generate CGLIB subclass of class [" + this.advised.getTargetClass() + "]: " + "Common causes of this problem include using a final class or a non-visible class", ex); } catch (Throwable ex) { // TargetSource.getTarget() failed throw new AopConfigException("Unexpected AOP exception", ex); } } |
下面进入JdkDynamicAopProxy的getProxy。根据我们对jdk动态代理的理解,通过实现InvocationHandler接口。然后返回一个对象。在进行动态代理的时候,会通过调用invoke方法
public Object getProxy(ClassLoader classLoader) { if (logger.isDebugEnabled()) { logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource()); } Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true); findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); //创建代理 return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); } |
紧接着我们分析下具体调用方法的时候,aop切入的过程。经过以上的步骤已经创建了对应的增强器,和代理类。进入JdkDynamicAopProxy的invoke
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { MethodInvocation invocation; Object oldProxy = null; boolean setProxyContext = false; //代理的目标类 TargetSource targetSource = this.advised.targetSource; Class<?> targetClass = null; Object target = null;
try { 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... return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); }
Object retVal;
if (this.advised.exposeProxy) { // Make invocation available if necessary. oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; }
// May be null. Get as late as possible to minimize the time we "own" the target, // in case it comes from a pool. target = targetSource.getTarget(); if (target != null) { targetClass = target.getClass(); }
// 获取拦截器链 List<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. Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } else { // 创建一个methodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); //不断的调用proceed 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); } } } |
下面进入内部类
public Object proceed() throws Throwable { // We start with an index of -1 and increment early. //判断当前的索引的值和拦截器连的size。 //执行完了所有的拦截方法,执行切点方法 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); } } |
通过上面的代码就将拦截器的执行过程构造成一个链路。
如当前的切点有实现了before和after切入。
那么list里边会存放三个拦截器分别为
ExposeInvocationInterceptor
AspectJAfterAdvice
MethodBeforeAdviceInterceptor
执行ExposeInvocationInterceptor方法的时候如下,将当前的methodInvocat放入线程变量相关,继续执行当前的proceed。
public Object invoke(MethodInvocation mi) throws Throwable { MethodInvocation oldInvocation = invocation.get(); invocation.set(mi); try { return mi.proceed(); } finally { invocation.set(oldInvocation); } } |
当前的索引进行++.进行AspectJAfterAdvice的invoke方法。从代码中可以看出,当前的代码继续执行methodInvocation的proceed。
@Override public Object invoke(MethodInvocation mi) throws Throwable { try { return mi.proceed(); } finally { invokeAdviceMethod(getJoinPointMatch(), null, null); } } |
而执行mi.proceed,当前的索引有重复++,执行对应的MethodBeforeAdviceInterceptor得invke方法
@Override public Object invoke(MethodInvocation mi) throws Throwable { //先调用before的增强方法 this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() ); //继续调用method.procced,当前调用要执行具体的切入点方法 //执行完,返回上一层。 return mi.proceed(); } |
经过上面,整个链路就执行完毕。