Spring的AOP底层解析
AOP原理的前置知识
(1)动态代理(具体可查看 java的动态代理底层解析 )
动态代理在Spring中的应用:
1.AOP
2.注解@Lazy
(2)Spring中针对动态代理的封装
1.ProxyFactory
(1)介绍
基于两种动态代理技术,在Spring中进行了封装,封装出来的类叫做ProxyFactory,表示是创建代理对象的一个工厂,使用起来会更加方便。
(2)简单使用
通过ProxyFactory,我们可以不再关系到底是用cglib还是jdk动态代理了,ProxyFactory会帮我们去判断,如果UserService实现了接口,那么ProxyFactory底层就会用jdk动态代理,如果没有实现接口,就会用cglib技术。
UserService userService1 = new UserService(); ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.setTarget(userService1); proxyFactory.addAdvice(new MethodInterceptor() { @Nullable @Override public Object invoke(@NotNull MethodInvocation invocation) throws Throwable { System.out.println("切面逻辑 before..."); Object result = invocation.proceed(); //执行被代理的方法,用于传递句柄 //invocation.getMethod().invoke(invocation.getThis(), invocation.getArguments()); //执行被代理对象的方法 System.out.println("切面逻辑 after..."); return result; } }); UserService userService2 = (UserService) proxyFactory.getProxy(); userService2.test();
(3)方法说明
1、setTarget(),创建一个单例的代理对象
2、addAdvice添加代理方法,该方法实现了Advice接口
3、getProxy() 获取代理对象,AOP代理的Bean是通过该方法增强的
(4)Advice的分类
据我们想要对方法增强的话会有以下情况:
1. Before Advice:方法之前执行(对应MethodBeforeAdvice接口)
public interface MethodBeforeAdvice extends BeforeAdvice { void before(Method method, Object[] args, @Nullable Object target) throws Throwable; }
2. After returning advice:方法return后执行 (对应AfterReturningAdvice接口)
public interface AfterReturningAdvice extends AfterAdvice { void afterReturning(@Nullable Object returnValue, Method method, Object[] args, @Nullable Object target) throws Throwable; }
3. After throwing advice:方法抛异常后执行(对应ThrowsAdvice接口)
/** * 注解上的示例 * <pre class="code">void afterThrowing([Method, args, target], ThrowableSubclass);</pre> * <p>Some examples of valid methods would be: * * <pre class="code">public void afterThrowing(Exception ex)</pre> * <pre class="code">public void afterThrowing(RemoteException)</pre> * <pre class="code">public void afterThrowing(Method method, Object[] args, Object target, Exception ex)</pre> * <pre class="code">public void afterThrowing(Method method, Object[] args, Object target, ServletException ex)</pre> */ public interface ThrowsAdvice extends AfterAdvice {} //为什么不定义方法,因为对于异常可以自定义,根据自己定义的不同异常进行捕捉执行拦截方法
4. After (finally) advice:方法执行完finally之后执行,这是最后的,比return更后(对应AfterAdvice接口)
5. Around advice:这是功能最强大的Advice,可以自定义执行顺序(对应MethodInterceptor接口)
/** * 注解上有着对应的示例 * <pre class=code> * class TracingInterceptor implements MethodInterceptor { * Object invoke(MethodInvocation i) throws Throwable { * System.out.println("method "+i.getMethod()+" is called on "+ * i.getThis()+" with args "+i.getArguments()); * Object ret=i.proceed(); * System.out.println("method "+i.getMethod()+" returns "+ret); * return ret; * } * } * </pre> */ public interface MethodInterceptor extends Interceptor { Object invoke(MethodInvocation invocation) throws Throwable; }
(5)链路形成的原理
1.addAdvice添加代理方法展示(既然有多个,那么调用的时候必然也要都调用)
//这个方法本质上最终是将advisor参数添加到this.advisors属性里面 public void addAdvisor(Advisor advisor) { int pos = this.advisors.size(); addAdvisor(pos, advisor); }
2.拦截器的句柄传递(分析invocation.proceed())
//ReflectiveMethodInvocation类#proceed()方法 public Object proceed() throws Throwable { // currentInterceptorIndex初始值为-1,每调用一个interceptor就会加1,当调用完了最后一个interceptor后就会执行被代理方法 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); } // currentInterceptorIndex初始值为-1,根据下标获取拦截器 Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); // 当前interceptor是InterceptorAndDynamicMethodMatcher,则先进行匹配,匹配成功后再调用该interceptor // 如果没有匹配则递归调用proceed()方法,调用下一个interceptor if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { 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 { // 不匹配则执行下一个MethodInterceptor return proceed(); } } else { // 直接调用MethodInterceptor,传入this,在内部会再次调用proceed()方法进行递归,如:MethodBeforeAdviceInterceptor return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } } protected Object invokeJoinpoint() throws Throwable { return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments); } AopUtils类#invokeJoinpointUsingReflection方法 public static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args) throws Throwable { try { ReflectionUtils.makeAccessible(method); // 执行普通对象的方法,注意和@Configuration产生的代理对象的逻辑区别 return method.invoke(target, args); } catch (InvocationTargetException ex) {...} catch (IllegalArgumentException ex) {...} catch (IllegalAccessException ex) {...} }
(6)Advisor的理解
1.介绍说明
跟Advice类似的还有一个Advisor的概念,一个Advisor是有一个Pointcut和一个Advice组成的,通过Pointcut可以指定要需要被代理的逻辑,比如一个UserService类中有两个方法,按上面的方法,这两个方法都会被代理,被增强,那么我们现在可以通过Advisor,来控制到具体代理哪一个方法。
2.代码示例(产生的代理对象,只有在执行testAbc这个方法时才会被增强,会执行额外的逻辑,而在执行其他方法时是不会增强的)
public class UserServiceImpl implements UserService { @Override public String doSomething0(String param) { System.out.println("==============doSomething0"); return "doSomething0"; } @Override public String doSomething1(String param) { System.out.println("==============doSomething1"); return "doSomething1"; } @Override public String doSomething2(String param) { System.out.println("==============doSomething2"); return "doSomething2"; } @Override public String myMethod(String param) { System.out.println("==============myMethod"); return "myMethod"; } } //操作代码 UserService userService1 = new UserServiceImpl(); ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.setTarget(userService1); proxyFactory.addAdvisor(new PointcutAdvisor() { @Override public Pointcut getPointcut() { return new StaticMethodMatcherPointcut() { @Override public boolean matches(Method method, Class<?> targetClass) { return method.getName().equals("doSomething1"); } }; } @Override public Advice getAdvice() { return new MyAroundAdvice(); } @Override public boolean isPerInstance() { return false; } }); UserService userService2 = (UserService) proxyFactory.getProxy(); userService2.doSomething0("456");
2.ProxyFactoryBean
(1)介绍
在使用Spring时,我们不会直接去使用ProxyFactory,因为我们希望所产生的代理对象能直接就是Bean能直接从Spring容器中得到代理对象,故使用ProxyFactoryBean。
(2)简单使用
通过这种方法来定义一个Bean,并且是经过了AOP的。但是这种方式只能针对某一个Bean。它是一个FactoryBean,所以利用的就是FactoryBean技术,间接的将类的代理对象作为了Bean。
方法1:
@Bean public ProxyFactoryBean userService1() { UserService userService = new UserService(); ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean(); proxyFactoryBean.setTarget(userService); proxyFactoryBean.addAdvisor(new PointcutAdvisor() { @Override public Pointcut getPointcut() { return new StaticMethodMatcherPointcut() { @Override public boolean matches(Method method, Class<?> targetClass) { return method.getName().equals("doSomething1"); } }; } @Override public Advice getAdvice() { return new MyAroundAdvice(); } @Override public boolean isPerInstance() { return false; } }); return proxyFactoryBean; }
方法2:
//把某个Advise或Advisor定义成为Bean,然后在ProxyFactoryBean中进行设置 @Bean public MyAroundAdvice MyAroundAdvise() { return new MyAroundAdvice(); } @Bean public ProxyFactoryBean userService() { UserService userService = new UserService(); ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean(); proxyFactoryBean.setProxyTargetClass(true); proxyFactoryBean.setTarget(userService); proxyFactoryBean.setInterceptorNames("myAroundAdvise"); return proxyFactoryBean; }
3.BeanNameAutoProxyCreator
(1)介绍
根据继承关系可知BeanNameAutoProxyCreator类继承了AbstractAdvisorAutoProxyCreator类(AbstractAutoProxyCreator有个抽象方法getAdvicesAndAdvisorsForBean方法)
该类实现SmartInstantiationAwareBeanPostProcessor接口(该接口继承InstantiationAwareBeanPostProcessor接口【用于实例化的接口】)
ProxyFactoryBean得自己指定被代理的对象,那么我们可以通过BeanNameAutoProxyCreator来通过指定某个bean的名字,来对该bean进行代理。
通过BeanNameAutoProxyCreator可以对批量的Bean进行AOP,并且指定了代理逻辑,指定了一个InterceptorName,也就是一个Advise,前提条件是这个Advise也得是一个Bean,这样Spring才能找到的,但是BeanNameAutoProxyCreator的缺点很明显,它只能根据beanName来指定想要代理的Bean。
(2)简单使用
@Bean public BeanNameAutoProxyCreator beanNameAutoProxyCreator() { BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator(); beanNameAutoProxyCreator.setBeanNames("userSe*"); beanNameAutoProxyCreator.setInterceptorNames("myAroundAdvise"); beanNameAutoProxyCreator.setProxyTargetClass(true); return beanNameAutoProxyCreator; }
4.DefaultAdvisorAutoProxyCreator
(1)介绍
根据继承关系可知DefaultAdvisorAutoProxyCreator类继承了AbstractAdvisorAutoProxyCreator类(AbstractAutoProxyCreator有个抽象方法getAdvicesAndAdvisorsForBean方法)
该类实现SmartInstantiationAwareBeanPostProcessor接口(该接口继承InstantiationAwareBeanPostProcessor接口【用于实例化的接口】)
(2)简单使用
@Bean public DefaultPointcutAdvisor defaultPointcutAdvisor() { NameMatchMethodPointcut pointcut = new NameMatchMethodPointcut(); pointcut.addMethodName("test"); DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor(); defaultPointcutAdvisor.setPointcut(pointcut); defaultPointcutAdvisor.setAdvice(new MyAroundAdvice()); return defaultPointcutAdvisor; } @Bean public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() { DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator(); defaultAdvisorAutoProxyCreator.setProxyTargetClass(true); return defaultAdvisorAutoProxyCreator; }
(3)思想说明
1.通过DefaultAdvisorAutoProxyCreator会去找所有Advisor类型的Bean,根据Advisor中的PointCut和Advice信息,确定要代理的Bean以及代理逻辑。
2.但通过这种方式,我们得依靠某一个类来实现定义我们的Advisor,或者Advise,或者Pointcut。
3.要知道在bean的生命周期中存在BeanDefinition获取bean的元数据,为了更简化那就通过注解。
4.通过在类中的方法上通过某些注解,来定义PointCut以及Advice,如
@Pointcut("execution(public * com.xxx.test.service.*.*(..))") public void pc1(){} @Around("pc1()") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("==============AspectAnnotation around前置通知========="); Object result = joinPoint.proceed(); System.out.println("==============AspectAnnotation around后置通知========="); return result; } //或者 @Around(""execution(public void com.xxx.test.service.UserService.test())"") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("==============AspectAnnotation around前置通知========="); Object result = joinPoint.proceed(); System.out.println("==============AspectAnnotation around后置通知========="); return result; }
5.直接定义好了所要代理的方法(通过一个表达式),以及代理逻辑(被@Before修饰的方法),这样对于Spring来说,它要做的就是来解析这些注解了,解析之后得到对应的Pointcut对象、Advice对象,生成Advisor对象,扔进ProxyFactory中,进而产生对应的代理对象。
5.TargetSource
(1)介绍
AOP中,被代理对象就是Bean对象,是由BeanFactory给我们创建出来的,但Spring AOP中提供了TargetSource机制,可以让我们用来自定义逻辑来创建被代理对象。
(2)简单使用
ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.setTargetSource(new TargetSource() { @Override public Class<?> getTargetClass() { return UserService.class; } @Override public boolean isStatic() { return true; } @Override public Object getTarget() throws Exception { return new UserService(); } @Override public void releaseTarget(Object target) throws Exception { } }); proxyFactory.addAdvice(new MyAroundAdvice()); proxyFactory.setProxyTargetClass(true); proxyFactory.setFrozen(true); // frozen和static都为true,可以使得代理对象执行方法是保证被代理对象是同一个 UserService proxy = (UserService) proxyFactory.getProxy(); proxy.test();
(3)简单说明
1.首先proxyFactory要产生代理对象离不开被代理对象。那么我们要先知道setTarget与setTargetSource之间的关联:
public void setTarget(Object target) { setTargetSource(new SingletonTargetSource(target)); } @Override public void setTargetSource(@Nullable TargetSource targetSource) { this.targetSource = (targetSource != null ? targetSource : EMPTY_TARGET_SOURCE); }
2.通过源码可以看到即使是设置Target,其实都会被包装成TargetSource,那么对应的要获取Target,也就只能调用TargetSource类#getTarget()方法。(说明proxy代理的不是target,而是TargetSource)
3.通常情况下,一个代理对象只能代理一个target,每次方法调用的目标也是唯一固定的target。但让proxy代理TargetSource,可以使得每次方法调用的target实例都不同(当然也可以相同,这取决于TargetSource实现)。这种机制使得方法调用变得灵活,可以扩展出很多高级功能,如:单利,原型,本地线程,目标对象池、运行时目标对象热替换目标源等等。(具体可查看 TargetSource目标源详解 )
对AOP的理解
- OOP表示面向对象编程,是一种编程思想,AOP表示面向切面编程,也是一种编程思想,而我们上面所描述的就是Spring为了让程序员更加方便的做到面向切面编程所提供的技术支持,也就说Spring提供了一套机制,可以让我们更加容易的来进行AOP,所以这套机制我们也可以称之为Spring AOP。
- 但提供的注解的方式来定义Pointcut和Advice,Spring并不是首创,首创是AspectJ,而且也不仅仅只有Spring提供了一套机制来支持AOP,还有比如 JBoss 4.0、aspectwerkz等技术都提供了对于AOP的支持。而且注解的方式,Spring是依赖了AspectJ的,Spring是直接把AspectJ中所定义的那些注解直接拿过来用,自己没有再重复定义了,也仅仅只是把注解的定义赋值过来了,每个注解具体底层是怎么解析的,还是Spring自己做的,所以在用Spring时,如果你想用@Before、@Around等注解,是需要单独引入aspecj相关jar包的。
- 注意:AspectJ是在编译时对字节码进行了修改,是直接在UserService类对应的字节码中进行增强的,也就是可以理解为是在编译时就会去解析@Before这些注解,然后得到代理逻辑,加入到被代理的类中的字节码中去的,所以如果想用AspectJ技术来生成代理对象 ,是需要用单独的AspectJ编译器的。我们在项目中很少这么用,仅仅只是用了@Before这些注解,而在启动Spring的过程中,Spring会去解析这些注解,然后利用动态代理机制生成代理对象的。
AOP中的核心概念
1. Aspect:表示切面,比如被@Aspect注解的类就是切面,可以在切面中去定义Pointcut、Advice等等
2. Join point:表示连接点,表示一个程序在执行过程中的一个点,比如一个方法的执行,比如一个异常的处理,在Spring AOP中,一个连接点通常表示一个方法的执行。
3. Advice:表示通知,表示在一个特定连接点上所采取的动作。Advice分为不同的类型,在Spring中是用Interceptor拦截器来实现Advice,并且在连接点周围维护一个Interceptor链。
4. Pointcut:表示切点,用来匹配一个或多个连接点,Advice与切点表达式是关联在一起的,Advice将会执行在和切点表达式所匹配的连接点上。
5. Introduction:可以使用@DeclareParents来给所匹配的类添加一个接口,并指定一个默认实现。(这种不怎么用)
示例
public interface CustomInterface { public void custom(); } public class DefaultCustomInterface implements CustomInterface{ @Override public void custom() { System.out.println("custom.."); } } @Aspect @Component public class MyAspect { //这种方式需要引入AspectJ @DeclareParents(value = "com.test.aop.introduction.CustomService", defaultImpl = DefaultCustomInterface.class) private CustomInterface customInterface; } @ComponentScan @Configuration @EnableAspectJAutoProxy public class IntroductionDemo { public static void main(String[] args) { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(IntroductionDemo.class); CustomService customService = applicationContext.getBean(CustomService.class); CustomInterface customInterface = (CustomInterface) customService; customInterface.custom(); } }
6. Target object:目标对象,被代理对象
7. AOP proxy:表示代理工厂,用来创建代理对象的,在Spring Framework中,要么是JDK动态代理,要么是CGLIB代理
8. Weaving:表示织入,表示创建代理对象的动作,这个动作可以发生在编译时期(比如Aspejctj),或者运行时【如Spring AOP】。
Advice在Spring AOP中对应API
(1)Aspject中的注解,其中有五个是用来定义Advice的,表示代理逻辑,以及执行时机:
1. @Before
2. @AfterReturning
3. @AfterThrowing
4. @After
5. @Around
(2)Spring自己也提供了类似的执行实际的实现类:
1. 接口MethodBeforeAdvice,继承了接口BeforeAdvice
2. 接口AfterReturningAdvice
3. 接口ThrowsAdvice
4. 接口AfterAdvice
5. 接口MethodInterceptor
(3)Spring会把五个注解解析为对应的Advice类:
1. @Before:AspectJMethodBeforeAdvice,实际上就是一个MethodBeforeAdvice
2. @AfterReturning:AspectJAfterReturningAdvice,实际上就是一个AfterReturningAdvice
3. @AfterThrowing:AspectJAfterThrowingAdvice,实际上就是一个MethodInterceptor
4. @After:AspectJAfterAdvice,实际上就是一个MethodInterceptor
5. @Around:AspectJAroundAdvice,实际上就是一个MethodInterceptor
ProxyFactory源码解析
1.怎么判断是使用哪种动态代理?
//ProxyFactory类#getProxy()方法 public Object getProxy() { //createAopProxy()在底层筛选方式 //getProxy()方法返回代理对象 return createAopProxy().getProxy(); } //ProxyCreatorSupport类#createAopProxy()方法 protected final synchronized AopProxy createAopProxy() { if (!this.active) { activate(); } //调用DefaultAopProxyFactory类(实现类AopProxyFactory接口)#createAopProxy(AdvisedSupport config)方法 return getAopProxyFactory().createAopProxy(this); } //DefaultAopProxyFactory类#createAopProxy方法 public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { // 是不是在GraalVM虚拟机上运行 if (!NativeDetector.inNativeImage() && // 如果ProxyFactory的isOptimize为true,Spring认为cglib比jdk动态代理要快 // 或者isProxyTargetClass为true // 或者ProxyFactory有没有添加接口[setInterfaces()方法] (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."); } //被代理的类是接口【setTargetClass】 //判断是不是已经被代理的类 if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } }
2.两种类型怎么产生动态代理的?
(1)CGLib动态代理
public Object getProxy() { return getProxy(null); } //删减日志与抛出异常部分 //CglibAopProxy类#getProxy方法 public Object getProxy(@Nullable ClassLoader classLoader) { try { // 被代理的类 Class<?> rootClass = this.advised.getTargetClass(); 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); // Configure CGLIB 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 ClassLoaderAwareGeneratorStrategy(classLoader)); // 获取和被代理类所匹配的Advisor 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 | IllegalArgumentException ex) {..} catch (Throwable ex) {..} }
(2)JDK动态代理
public Object getProxy() { return getProxy(ClassUtils.getDefaultClassLoader()); } //JdkDynamicAopProxy类#getProxy方法 public Object getProxy(@Nullable ClassLoader classLoader) { // this实现了InvocationHandler return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this); }
3.两种类型的执行逻辑是怎么样的?
(1)JDK动态代理
1.JdkDynamicAopProxy类#invoke方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object oldProxy = null; boolean setProxyContext = false; // 拿到ProxyFactory的配置对象【属性值private final AdvisedSupport advised;(AdvisedSupport是实现ProxyConfig配置接口的)】 TargetSource targetSource = this.advised.targetSource; Object target = null; try { //判断如果被代理的目标对象要执行的方法是equal则执行JdkDynamicAopProxy(即代理对象的equal)方法,说明spring不对equal方法进行AOP拦截 if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { return equals(args[0]); } //判断如果被代理的目标对象要执行的方法是hashcode则执行JdkDynamicAopProxy(即代理对象的hashcode)方法,同理spring也不对hashcode进行AOP拦截 else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { return hashCode(); } else if (method.getDeclaringClass() == DecoratingProxy.class) { // 得到代理对象的类型,而不是所实现的接口 return AopProxyUtils.ultimateTargetClass(this.advised); } //判断如果被代理的对象本身就是实现了Advised接口,也不做处理,直接执行,说明spring不做切面的切面 else if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); } Object retVal; // 如果ProxyFactory的exposeProxy为true(可以对外暴露),则将代理对象设置到currentProxy这个ThreadLocal中去 if (this.advised.exposeProxy) { //将代理对象设置到currentProxy这个ThreadLocal中去,作用是能通过ThreadLocal获取当前的代理对象(能在自己写的方法里面拿到代理对象) oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } // 被代理对象和代理类 target = targetSource.getTarget(); Class<?> targetClass = (target != null ? target.getClass() : null); // 代理对象在执行某个方法时,根据方法筛选出匹配的Advisor,并适配成Interceptor List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); if (chain.isEmpty()) { // 如果没有Advice,则直接调用对应方法 Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } else { //包装成方法对象反射调用句柄 MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, 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())) { 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()) { targetSource.releaseTarget(target); } if (setProxyContext) { AopContext.setCurrentProxy(oldProxy); } } }
2.AdvisedSupport类#getInterceptorsAndDynamicInterceptionAdvice方法
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; }
3.DefaultAdvisorChainFactory类#getInterceptorsAndDynamicInterceptionAdvice方法
//DefaultAdvisorChainFactory类#getInterceptorsAndDynamicInterceptionAdvice方法 public List<Object> getInterceptorsAndDynamicInterceptionAdvice( Advised config, Method method, @Nullable Class<?> targetClass) { AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance(); // 从ProxyFactory中拿到所设置的Advice(添加时被封装成了DefaultPointcutAdvisor),添加的时候会控制顺序 Advisor[] advisors = config.getAdvisors(); List<Object> interceptorList = new ArrayList<>(advisors.length); Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass()); Boolean hasIntroductions = null; //遍历每个advisor for (Advisor advisor : advisors) { if (advisor instanceof PointcutAdvisor) { 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,也是ThrowsAdvice MethodInterceptor[] interceptors = registry.getInterceptors(advisor); if (mm.isRuntime()) { for (MethodInterceptor interceptor : interceptors) {
// 运行时,封装成对应的 InterceptorAndDynamicMethodMatcher 拦截器对象。 interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm)); } } else { interceptorList.addAll(Arrays.asList(interceptors)); } } // 最终,interceptorList中存储的是当前正在执行的Method所匹配的MethodInterceptor,可能动态的,也可能是非动态的, // 找到Method所匹配的MethodInterceptor后,就会开始调用这些MethodInterceptor,如果是动态的,会额外进行方法参数的匹配 } } //下面便是采用了修饰器模式的思维,把所有的拦截类型都转为Interceptor方便后面调用 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封装成为Interceptor Interceptor[] interceptors = registry.getInterceptors(advisor); interceptorList.addAll(Arrays.asList(interceptors)); } } return interceptorList; }
4.DefaultAdvisorAdapterRegistry类#getInterceptors方法(拦截器包装)
//作用是将advisor封装成MethodInterceptor public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException { List<MethodInterceptor> interceptors = new ArrayList<>(3); Advice advice = advisor.getAdvice(); if (advice instanceof MethodInterceptor) { interceptors.add((MethodInterceptor) advice); } // 将Advice适配成MethodInterceptor for (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]); } //初始化的时候就进行了适配器填充 private final List<AdvisorAdapter> adapters = new ArrayList<>(3); public DefaultAdvisorAdapterRegistry() { registerAdvisorAdapter(new MethodBeforeAdviceAdapter()); //作用:包装成new MethodBeforeAdviceInterceptor(advice); registerAdvisorAdapter(new AfterReturningAdviceAdapter()); //作用:包装成new AfterReturningAdviceInterceptor(advice); registerAdvisorAdapter(new ThrowsAdviceAdapter()); //作用:包装成new ThrowsAdviceInterceptor(advisor.getAdvice()); } public void registerAdvisorAdapter(AdvisorAdapter adapter) { this.adapters.add(adapter); }
5.包装拦截器的部分展示
//主要展示invoke逻辑 public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable { .... @Override public Object invoke(MethodInvocation mi) throws Throwable { this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis()); return mi.proceed(); } ... } public class ThrowsAdviceInterceptor implements MethodInterceptor, AfterAdvice { ... @Override public Object invoke(MethodInvocation mi) throws Throwable { try { return mi.proceed(); } catch (Throwable ex) { Method handlerMethod = getExceptionHandler(ex); if (handlerMethod != null) { invokeHandlerMethod(mi, ex, handlerMethod); } throw ex; } } ... } public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable { ... @Override public Object invoke(MethodInvocation mi) throws Throwable { Object retVal = mi.proceed(); this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis()); return retVal; } ... } //运行时会进行的封装,因为运行时的方法匹配需要传参 class InterceptorAndDynamicMethodMatcher { final MethodInterceptor interceptor; final MethodMatcher methodMatcher; public InterceptorAndDynamicMethodMatcher(MethodInterceptor interceptor, MethodMatcher methodMatcher) { this.interceptor = interceptor; this.methodMatcher = methodMatcher; } }
6.PointcutAdvisor说明(前面如果不太理解的重点要把这个advisor与pointcut与advice关系梳理好)
(1)使用示例
public class MyPointcutAdvisor implements PointcutAdvisor { @Override public Pointcut getPointcut() { return new Pointcut() { @Override //返回当前切点匹配的类 public ClassFilter getClassFilter() { // return ClassFilter.TRUE;//所有类都匹配 return new ClassFilter() { @Override //匹配逻辑的写法 public boolean matches(Class<?> clazz) { return clazz.equals(UserService.class); } }; } @Override //返回当前切点匹配的方法 public MethodMatcher getMethodMatcher() { // return MethodMatcher.TRUE;所有方法都匹配 return new MethodMatcher() { @Override //静态方法匹配器 public boolean matches(Method method, Class<?> targetClass) { return false; } @Override //返回false表示是静态方法匹配器,返回true表示是动态方法匹配器 public boolean isRuntime() { return false; } @Override //动态方法匹配器 public boolean matches(Method method, Class<?> targetClass, Object... args) { return false; } }; } }; } @Override public Advice getAdvice() { return new MyAroundAdvice(); } @Override public boolean isPerInstance() { return false; } }
(2)CGLib动态代理
1.在CGLIB动态代理中,拦截器会被包装成DynamicAdvisedInterceptor类,调用时是调用DynamicAdvisedInterceptor类#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 { if (this.advised.exposeProxy) { oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } target = targetSource.getTarget(); Class<?> targetClass = (target != null ? target.getClass() : null); // 获取当前方法的拦截器链,并执行调用 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); Object retVal; // 检测是否拦截器链是否为空,如果拦截器链为空,那么直接通过反射调用目标对象的方法,避免创建MethodInvocation if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) { // 通过反射直接调用目标对象的方法 Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = methodProxy.invoke(target, argsToUse); } else { //拦截器链的调用方法proceed与JDK动态代理的proceed是一样的。 // 创建CglibMethodInvocation对象并调用proceed方法,拦截器链被封装到了retVal中 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) { AopContext.setCurrentProxy(oldProxy); } } }
AOP的引入
1.核心概念说明
(1)AbstractAdvisorAutoProxyCreator类
- DefaultAdvisorAutoProxyCreator的父类是AbstractAdvisorAutoProxyCreator。
- AbstractAdvisorAutoProxyCreator非常强大以及重要,只要Spring容器中存在这个类型的Bean,就相当于开启了AOP。
-
AbstractAdvisorAutoProxyCreator实际上就是一个BeanPostProcessor,所以在创建某个Bean时,就会进入到它对应的生命周期方法中,比如:在某
个Bean初始化之后,会调用wrapIfNecessary()方法进行AOP,底层逻辑是,AbstractAdvisorAutoProxyCreator会找到所有的Advisor,然后判断当前这个Bean是否存在某个Advisor与之匹配(根据Pointcut),如果匹配就表示当前这个Bean有对应的切面逻辑,需要进行AOP,需要产生一个代理对象。
- DefaultAdvisorAutoProxyCreator的父类是AbstractAdvisorAutoProxyCreator。
(2)注解@EnableAspectJAutoProxy
-
这个注解主要就是往Spring容器中添加了一个AnnotationAwareAspectJAutoProxyCreator类型的Bean。
- AspectJAwareAdvisorAutoProxyCreator继承了AbstractAdvisorAutoProxyCreator,重写了findCandidateAdvisors()方法,AbstractAdvisorAutoProxyCreator只能找到所有Advisor类型的Bean对象,但是AspectJAwareAdvisorAutoProxyCreator除开可以找到所有Advisor类型的Bean对象,还能把@Aspect注解所标注的Bean中的@Before等注解及方法进行解析,并生成对应的Advisor对象。
-
所以,我们可以理解@EnableAspectJAutoProxy,其实就是像Spring容器中添加了一个AbstractAdvisorAutoProxyCreator类型的Bean,从而开启了AOP,并且还会解析@Before等注解生成Advisor。
-
2.注解@EnableAspectJAutoProxy的源码分析 (导入AspectJAutoProxyRegistrar类)
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions( AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { //注册注解AOP入口类(AnnotationAwareAspectJAutoProxyCreator.class) AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry); /* * * true * 1、目标对象实现了接口 – 使用CGLIB代理机制 * 2、目标对象没有接口(只有实现类) – 使用CGLIB代理机制 * * false * 1、目标对象实现了接口 – 使用JDK动态代理机制(代理所有实现了的接口) * 2、目标对象没有接口(只有实现类) – 使用CGLIB代理机制 * */ AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class); if (enableAspectJAutoProxy != null) { if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); } //是否需要把代理对象暴露出来,简单来说是否需要把代理对象用ThreadLocal存起来,如果是true就是需要 if (enableAspectJAutoProxy.getBoolean("exposeProxy")) { AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry); } } } } //核心点 AnnotationAwareAspectJAutoProxyCreator类的继承关系【】 extends AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator AbstractAutoProxyCreator extends ProxyProcessorSupport(这个不重要) implements SmartInstantiationAwareBeanPostProcessor(这个很重要) extends InstantiationAwareBeanPostProcessor (该接口用于实例化) extends BeanPostProcessor(该接口用于初始化前后)
AOP代码的执行逻辑
1.了解Bean的生命周期,直接跳到初始化后的那一步。AbstractAutowireCapableBeanFactory类#doCreateBean方法里的initializeBean(beanName, exposedObject, mbd)方法。
if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); }
2.AnnotationAwareAspectJAutoProxyCreator处理器进行处理
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor processor : getBeanPostProcessors()) { //拿到AnnotationAwareAspectJAutoProxyCreator处理器进行处理 Object current = processor.postProcessAfterInitialization(result, beanName); if (current == null) { return result; } result = current; } return result; }
3.走到AnnotationAwareAspectJAutoProxyCreator类的父类AbstractAutoProxyCreator类的逻辑:
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.contains(cacheKey)) { return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }
4.wrapIfNecessary方法内判断是否进行AOP:
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { return bean; } // advisedBeans表示已经判断过了的bean,false表示此bean不需要进行Aop if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } // 判断Bean的类是否和切面有关(切面Bean不会被代理) // shouldSkip,提供扩展定义哪些类不用进行AOP(其实没怎么用,故不关注) if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } // 判断当前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); //不进行AOP则返回原本的Bean return bean; }
5.getAdvicesAndAdvisorsForBean方法能否收集到Interceptors是能否进行AOP的重要标记:
//AbstractAdvisorAutoProxyCreator类#getAdvicesAndAdvisorsForBean方法 protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) { // 寻找匹配的Advisor List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName); if (advisors.isEmpty()) { return DO_NOT_PROXY; } return advisors.toArray(); } //AbstractAdvisorAutoProxyCreator类#findEligibleAdvisors方法 protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { // 找到所有的Advisor List<Advisor> candidateAdvisors = findCandidateAdvisors(); // 进行筛选 List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);【支线(3)】 //这是留给子类的扩展(本身没有做什么东西) extendAdvisors(eligibleAdvisors); // 对Advisor进行排序,按Ordered接口、@Order注解进行排序 if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; } //AnnotationAwareAspectJAutoProxyCreator类#findCandidateAdvisors方法 protected List<Advisor> findCandidateAdvisors() { // 先从Bean工厂中找到所有Advisor类型【也就是实现Advisor接口】的Bean对象【支线(1)】 List<Advisor> advisors = super.findCandidateAdvisors(); // 再从所有切面中解析得到Advisor对象【也就是被注解@Aspect修饰的Bean】 if (this.aspectJAdvisorsBuilder != null) { advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());【支线(2)】 } return advisors; }
(1)AbstractAdvisorAutoProxyCreator类#findCandidateAdvisors方法
//AbstractAdvisorAutoProxyCreator类#findCandidateAdvisors方法 protected List<Advisor> findCandidateAdvisors() { return this.advisorRetrievalHelper.findAdvisorBeans(); } //BeanFactoryAdvisorRetrievalHelper类#findAdvisorBeans方法 public List<Advisor> findAdvisorBeans() { // Determine list of advisor bean names, if not cached already. String[] advisorNames = this.cachedAdvisorBeanNames; if (advisorNames == null) { // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let the auto-proxy creator apply to them! advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Advisor.class, true, false); this.cachedAdvisorBeanNames = advisorNames; } if (advisorNames.length == 0) { return new ArrayList<>(); } List<Advisor> advisors = new ArrayList<>(); for (String name : advisorNames) { if (isEligibleBean(name)) { if (this.beanFactory.isCurrentlyInCreation(name)) { if (logger.isTraceEnabled()) { logger.trace("Skipping currently created advisor '" + name + "'"); } } else { try { //从Bean工厂中找出所有实现Advisor接口的Bean advisors.add(this.beanFactory.getBean(name, Advisor.class)); } catch (BeanCreationException ex) { Throwable rootCause = ex.getMostSpecificCause(); if (rootCause instanceof BeanCurrentlyInCreationException) { BeanCreationException bce = (BeanCreationException) rootCause; String bceBeanName = bce.getBeanName(); if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) { if (logger.isTraceEnabled()) { logger.trace("Skipping advisor '" + name + "' with dependency on currently created bean: " + ex.getMessage()); } // Ignore: indicates a reference back to the bean we're trying to advise. // We want to find advisors other than the currently created bean itself. continue; } } throw ex; } } } } return advisors; }
(2)BeanFactoryAspectJAdvisorsBuilder类#buildAspectJAdvisors方法(封装的Advisor是InstantiationModelAwarePointcutAdvisorImpl类):
//BeanFactoryAspectJAdvisorsBuilder类#buildAspectJAdvisors方法 //本方法会被多次调用,因为一个Bean在判断要不要进行AOP时,都会调用这个方法 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的类型是否是Aspect String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Object.class, true, false); for (String beanName : beanNames) { if (!isEligibleBean(beanName)) { continue; } // We must be careful not to instantiate beans eagerly as in this case they // would be cached by the Spring container but would not have been weaved. Class<?> beanType = this.beanFactory.getType(beanName, false); if (beanType == null) { continue; } //判断Bean的类型上是不是有@Aspect注解 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类【将里面的很多切面方法变成Advisor数组】 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));【调用1】 } } } this.aspectBeanNames = aspectNames; return advisors; } } } if (aspectNames.isEmpty()) { return Collections.emptyList(); } // 如果切面已经找到过了,那么则遍历每个切面是否缓存了对应的Advisor,如果没有缓存则进行解析得到Advisor List<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));【调用1】 } } return advisors; } //ReflectiveAspectJAdvisorFactory类#getAdvisors方法;【调用1】 public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) { Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass(); String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName(); validate(aspectClass); // 保证切面Bean对象只会实例化一次 // 一定要注意,这里是直接new出来一个LazySingletonAspectInstanceFactoryDecorator // 也就是OrderService这个Bean在执行Bean生命周期过程中,会需要判断要不要进行AOP,就会找到切面, // 发现切面如果是pertarget或perthis,那么就会进入到这个方法,就会new一个LazySingletonAspectInstanceFactoryDecorator // 对于UserService也是一样的,在它的Bean的生命周期过程中,也会进入到这个方法,也会new一个LazySingletonAspectInstanceFactoryDecorator MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory); List<Advisor> advisors = new ArrayList<>(); // 获取切面类中没有加@Pointcut的方法,进行遍历生成Advisor for (Method method : getAdvisorMethods(aspectClass)) {【调用2】 Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);【调用3】 if (advisor != null) { advisors.add(advisor); } } // If it's a per target aspect, emit the dummy instantiating aspect. // @Aspect("pertarget(this(com.zhouyu.service.UserService))") // @Aspect("perthis(this(com.zhouyu.service.UserService))") // 如果是pertarget或perthis,则会多生成一个Advisor并放在最前面 // 在一个代理对象调用方法的时候,就会执行该Advisor,并且会利用lazySingletonAspectInstanceFactory来生成一个切面Bean if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) { Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory); advisors.add(0, instantiationAdvisor); } // Find introduction fields. // 找到哪些字段上加了@DeclareParents注解,把这些字段以及对于的注解解析封装为Advisor,生成代理对象时会把对于的接口添加到ProxyFactory中 for (Field field : aspectClass.getDeclaredFields()) { Advisor advisor = getDeclareParentsAdvisor(field); if (advisor != null) { advisors.add(advisor); } } return advisors; } //ReflectiveAspectJAdvisorFactory类#getAdvisorMethods方法【调用2】 private List<Method> getAdvisorMethods(Class<?> aspectClass) { List<Method> methods = new ArrayList<>(); // 拿到切面类中所有没有加@Pointcut的方法 ReflectionUtils.doWithMethods(aspectClass, methods::add, adviceMethodFilter); // 对方法进行排序,按注解和方法名字进行排序 if (methods.size() > 1) { methods.sort(adviceMethodComparator); } return methods; } //ReflectiveAspectJAdvisorFactory类#getAdvisor方法【调用3】 public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrderInAspect, String aspectName) { validate(aspectInstanceFactory.getAspectMetadata().getAspectClass()); // 拿到当前方法所对应的Pointcut对象,但是注意:如果当前方法上是这么写的@After("pointcut()"),那么此时得到的Pointcut并没有去解析pointcut()得到对应的表达式 AspectJExpressionPointcut expressionPointcut = getPointcut( candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass()); if (expressionPointcut == null) { return null; } // expressionPointcut是pointcut // candidateAdviceMethod承载了advice return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod, this, aspectInstanceFactory, declarationOrderInAspect, aspectName); }
(3)BeanFactoryAspectJAdvisorsBuilder类#buildAspectJAdvisors方法:
//AbstractAdvisorAutoProxyCreator类#findAdvisorsThatCanApply方法 protected List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) { ProxyCreationContext.setCurrentProxiedBeanName(beanName); try { return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);【调用1】 } finally { ProxyCreationContext.setCurrentProxiedBeanName(null); } } //AopUtils类#findAdvisorsThatCanApply方法【调用1】 public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) { if (candidateAdvisors.isEmpty()) { return candidateAdvisors; } List<Advisor> eligibleAdvisors = new ArrayList<>(); 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; }
6.createProxy方法进行AOP代理逻辑:
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); } ProxyFactory 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); proxyFactory.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 loader ClassLoader classLoader = getProxyClassLoader(); if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) { classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader(); } //这里面便是要走我们之前所说的proxyFactory的逻辑 return proxyFactory.getProxy(classLoader); }
7.分析基于注解产生的Advisor的具体实现类InstantiationModelAwarePointcutAdvisorImpl类:
//InstantiationModelAwarePointcutAdvisorImpl类#getAdvice方法 public synchronized Advice getAdvice() { if (this.instantiatedAdvice == null) { this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);【调用1】 } return this.instantiatedAdvice; } //调用1 private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) { Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut, this.aspectInstanceFactory, this.declarationOrder, this.aspectName);//【调用2】 return (advice != null ? advice : EMPTY_ADVICE); } //【调用2】 //ReflectiveAspectJAdvisorFactory类#getAdvice方法 public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) { Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass(); validate(candidateAspectClass); // 拿到当前candidateAdviceMethod方法上的注解信息 AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod); if (aspectJAnnotation == null) { return null; } // If we get here, we know we have an AspectJ method. // Check that it's an AspectJ-annotated class if (!isAspect(candidateAspectClass)) { throw new AopConfigException("Advice must be declared inside an aspect type: " + "Offending method '" + candidateAdviceMethod + "' in class [" + candidateAspectClass.getName() + "]"); } if (logger.isDebugEnabled()) { logger.debug("Found AspectJ method: " + candidateAdviceMethod); } AbstractAspectJAdvice springAdvice; // 按不同的注解类型得到不同的Advice switch (aspectJAnnotation.getAnnotationType()) { case AtPointcut: if (logger.isDebugEnabled()) { logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'"); } return null; case AtAround: // @Around springAdvice = new AspectJAroundAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); break; case AtBefore: springAdvice = new AspectJMethodBeforeAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); break; case AtAfter: springAdvice = new AspectJAfterAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); break; case AtAfterReturning: springAdvice = new AspectJAfterReturningAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation(); if (StringUtils.hasText(afterReturningAnnotation.returning())) { springAdvice.setReturningName(afterReturningAnnotation.returning()); } break; case AtAfterThrowing: springAdvice = new AspectJAfterThrowingAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation(); if (StringUtils.hasText(afterThrowingAnnotation.throwing())) { springAdvice.setThrowingName(afterThrowingAnnotation.throwing()); } break; default: throw new UnsupportedOperationException( "Unsupported advice type on method: " + candidateAdviceMethod); } // Now to configure the advice... springAdvice.setAspectName(aspectName); springAdvice.setDeclarationOrder(declarationOrder); String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod); if (argNames != null) { springAdvice.setArgumentNamesFromStringArray(argNames); } springAdvice.calculateArgumentBindings(); return springAdvice; }
AOP底层原理图示
AOP涉及的设计模式
1.装饰器模式:主要体现在责任链构建中拦截器的包装。
2.代理模式:主要体现在ProxyFactory生成动态代理。
3.适配器模式:DefaultAdvisorAdapterRegistry类#getInterceptors方法的选择合适的适配器进行拦截器的包装。
4.策略模式:主要体现在ProxyFactory选择动态代理类型。
5.责任链模式:主要体现在构建调用链。
6.模板设计模式:主要体现在,抽象模板:AbstractAutoProxyCreator类;具体的模板:AnnotationAwareAspectJAutoProxyCreator类。