个人随笔
Spring源码分析:SpringAOP源码分析(五)
2020-09-28 23:06:13

之前写过 IOC 的源码分析,那篇文章真的有点长,看完需要点耐心。很多读者希望能写一写 Spring AOP 的源码分析文章,这样读者看完 IOC + AOP 也就对 Spring 会有比较深的理解了。今天终于成文了,可能很多读者早就不再等待了,不过主要为了后来者吧。

本文不会像 IOC 源码分析那篇文章一样,很具体地分析每一行 Spring AOP 的源码,目标读者是已经知道 Spring IOC 源码是怎么回事的读者,因为 Spring AOP 终归是依赖于 IOC 容器来管理的。

阅读建议:Spring源码分析:SpringIOC初始化过程源码分析-基于配置文件模式(三)

Spring AOP 的源码并不简单,因为它多,所以阅读源码最好就是找到一个分支,追踪下去。本文定位为走马观花,看个大概,不具体到每一个细节。

前言

这一节,我们先来”猜猜” Spring 是怎么实现 AOP 的。

在 Spring 的容器中,我们面向的对象是一个个的 bean 实例,bean 是什么?我们可以简单理解为是 BeanDefinition 的实例,Spring 会根据 BeanDefinition 中的信息为我们生产合适的 bean 实例出来。

当我们需要使用 bean 的时候,通过 IOC 容器的 getBean(…) 方法从容器中获取 bean 实例,只不过大部分的场景下,我们都用了依赖注入,所以很少手动调用 getBean(…) 方法。

Spring AOP 的原理很简单,就是动态代理,它和 AspectJ 不一样,AspectJ 是直接修改掉你的字节码。

代理模式很简单,接口 + 真实实现类 + 代理类,其中 真实实现类 和 代理类 都要实现接口,实例化的时候要使用代理类。所以,Spring AOP 需要做的是生成这么一个代理类,然后替换掉真实实现类来对外提供服务。

替换的过程怎么理解呢?在 Spring IOC 容器中非常容易实现,就是在 getBean(…) 的时候返回的实际上是代理类的实例,而这个代理类我们自己没写代码,它是 Spring 采用 JDK Proxy 或 CGLIB 动态生成的。

getBean(…) 方法用于查找或实例化容器中的 bean,这也是为什么 Spring AOP 只能作用于 Spring 容器中的 bean 的原因,对于不是使用 IOC 容器管理的对象,Spring AOP 是无能为力的。

本文使用的调试代码

阅读源码很好用的一个方法就是跑代码来调试,因为自己一行一行地看的话,比较枯燥,而且难免会漏掉一些东西。

下面,我们先准备一些简单的调试用的代码。

首先先定义两个 Service 接口:

  1. // OrderService.java
  2. public interface OrderService {
  3. Order createOrder(String username, String product);
  4. Order queryOrder(String username);
  5. }
  6. // UserService.java
  7. public interface UserService {
  8. User createUser(String firstName, String lastName, int age);
  9. User queryUser();
  10. }

然后,分别来一个接口实现类:

  1. // OrderServiceImpl.java
  2. public class OrderServiceImpl implements OrderService {
  3. @Override
  4. public Order createOrder(String username, String product) {
  5. Order order = new Order();
  6. order.setUsername(username);
  7. order.setProduct(product);
  8. return order;
  9. }
  10. @Override
  11. public Order queryOrder(String username) {
  12. Order order = new Order();
  13. order.setUsername("test");
  14. order.setProduct("test");
  15. return order;
  16. }
  17. }
  18. // UserServiceImpl.java
  19. public class UserServiceImpl implements UserService {
  20. @Override
  21. public User createUser(String firstName, String lastName, int age) {
  22. User user = new User();
  23. user.setFirstName(firstName);
  24. user.setLastName(lastName);
  25. user.setAge(age);
  26. return user;
  27. }
  28. @Override
  29. public User queryUser() {
  30. User user = new User();
  31. user.setFirstName("test");
  32. user.setLastName("test");
  33. user.setAge(20);
  34. return user;
  35. }
  36. }

写两个 Advice:

  1. public class LogArgsAdvice implements MethodBeforeAdvice {
  2. @Override
  3. public void before(Method method, Object[] args, Object target) throws Throwable {
  4. System.out.println("准备执行方法: " + method.getName() + ", 参数列表:" + Arrays.toString(args));
  5. }
  6. }
  1. public class LogResultAdvice implements AfterReturningAdvice {
  2. @Override
  3. public void afterReturning(Object returnValue, Method method, Object[] args, Object target)
  4. throws Throwable {
  5. System.out.println(method.getName() + "方法返回:" + returnValue);
  6. }
  7. }

配置一下:

我们这边使用了前面文章介绍的配置 Advisor 的方式,我们回顾一下。

每个 advisor 内部持有 advice 实例,advisor 负责匹配,内部的 advice 负责实现拦截处理。配置了各个 advisor 后,配置 DefaultAdvisorAutoProxyCreator 使得所有的 advisor 配置自动生效。

启动:

  1. public class SpringAopSourceApplication {
  2. public static void main(String[] args) {
  3. // 启动 Spring 的 IOC 容器
  4. ApplicationContext context = new ClassPathXmlApplicationContext("classpath:DefaultAdvisorAutoProxy.xml");
  5. UserService userService = context.getBean(UserService.class);
  6. OrderService orderService = context.getBean(OrderService.class);
  7. userService.createUser("Tom", "Cruise", 55);
  8. userService.queryUser();
  9. orderService.createOrder("Leo", "随便买点什么");
  10. orderService.queryOrder("Leo");
  11. }
  12. }

输出:

  1. 准备执行方法: createUser, 参数列表:[Tom, Cruise, 55]
  2. queryUser方法返回:User{firstName='test', lastName='test', age=20, address='null'}
  3. 准备执行方法: createOrder, 参数列表:[Leo, 随便买点什么]
  4. queryOrder方法返回:Order{username='test', product='test'}

从输出结果,我们可以看到:

LogArgsAdvice 作用于 UserService#createUser(…) 和 OrderService#createOrder(…) 两个方法;

LogResultAdvice 作用于 UserService#queryUser() 和 OrderService#queryOrder(…) 两个方法;

下面的代码分析中,我们将基于这个简单的例子来介绍。

IOC 容器管理 AOP 实例

本节介绍 Spring AOP 是怎么作用于 IOC 容器中的 bean 的。

Spring AOP 的使用介绍 那篇文章已经介绍过 DefaultAdvisorAutoProxyCreator 类了,它能实现自动将所有的 advisor 生效。

我们来追踪下 DefaultAdvisorAutoProxyCreator 类,看看它是怎么一步步实现的动态代理。然后在这个基础上,我们再简单追踪下 @AspectJ 配置方式下的源码实现。

首先,先看下 DefaultAdvisorAutoProxyCreator 的继承结构:

我们可以发现,DefaultAdvisorAutoProxyCreator 最后居然是一个 BeanPostProcessor,在 Spring IOC 源码分析的时候说过,BeanPostProcessor 的两个方法,分别在 init-method 的前后得到执行。

  1. public interface BeanPostProcessor {
  2. Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
  3. Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
  4. }

这里再贴一下 IOC 的源码,我们回顾一下:

// AbstractAutowireCapableBeanFactory

  1. protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
  2. throws BeanCreationException {
  3. // Instantiate the bean.
  4. BeanWrapper instanceWrapper = null;
  5. if (mbd.isSingleton()) {
  6. instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
  7. }
  8. if (instanceWrapper == null) {
  9. // 1. 创建实例
  10. instanceWrapper = createBeanInstance(beanName, mbd, args);
  11. }
  12. ...
  13. // Initialize the bean instance.
  14. Object exposedObject = bean;
  15. try {
  16. // 2. 装载属性
  17. populateBean(beanName, mbd, instanceWrapper);
  18. if (exposedObject != null) {
  19. // 3. 初始化
  20. exposedObject = initializeBean(beanName, exposedObject, mbd);
  21. }
  22. }
  23. ...
  24. }

在上面第 3 步 initializeBean(…) 方法中会调用 BeanPostProcessor 中的方法,如下:

  1. protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
  2. ...
  3. Object wrappedBean = bean;
  4. if (mbd == null || !mbd.isSynthetic()) {
  5. // 1. 执行每一个 BeanPostProcessor 的 postProcessBeforeInitialization 方法
  6. wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
  7. }
  8. try {
  9. // 调用 bean 配置中的 init-method="xxx"
  10. invokeInitMethods(beanName, wrappedBean, mbd);
  11. }
  12. ...
  13. if (mbd == null || !mbd.isSynthetic()) {
  14. // 我们关注的重点是这里!!!
  15. // 2. 执行每一个 BeanPostProcessor 的 postProcessAfterInitialization 方法
  16. wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
  17. }
  18. return wrappedBean;
  19. }

也就是说,Spring AOP 会在 IOC 容器创建 bean 实例的最后对 bean 进行处理。其实就是在这一步进行代理增强。

我们回过头来,DefaultAdvisorAutoProxyCreator 的继承结构中,postProcessAfterInitialization() 方法在其父类 AbstractAutoProxyCreator 这一层被覆写了:

// AbstractAutoProxyCreator

  1. @Override
  2. public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  3. if (bean != null) {
  4. Object cacheKey = getCacheKey(bean.getClass(), beanName);
  5. if (!this.earlyProxyReferences.contains(cacheKey)) {
  6. return wrapIfNecessary(bean, beanName, cacheKey);
  7. }
  8. }
  9. return bean;
  10. }

继续往里看 wrapIfNecessary(…) 方法,这个方法将返回代理类(如果需要的话):

  1. protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
  2. if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
  3. return bean;
  4. }
  5. if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
  6. return bean;
  7. }
  8. if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
  9. this.advisedBeans.put(cacheKey, Boolean.FALSE);
  10. return bean;
  11. }
  12. // 返回匹配当前 bean 的所有的 advisor、advice、interceptor
  13. // 对于本文的例子,"userServiceImpl" 和 "OrderServiceImpl" 这两个 bean 创建过程中,
  14. // 到这边的时候都会返回两个 advisor
  15. Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
  16. if (specificInterceptors != DO_NOT_PROXY) {
  17. this.advisedBeans.put(cacheKey, Boolean.TRUE);
  18. // 创建代理...创建代理...创建代理...
  19. Object proxy = createProxy(
  20. bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
  21. this.proxyTypes.put(cacheKey, proxy.getClass());
  22. return proxy;
  23. }
  24. this.advisedBeans.put(cacheKey, Boolean.FALSE);
  25. return bean;
  26. }

这里有两个点提一下:

getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null),这个方法将得到所有的可用于拦截当前 bean 的 advisor、advice、interceptor。

另一个就是 TargetSource 这个概念,它用于封装真实实现类的信息,上面用了 SingletonTargetSource 这个实现类,其实我们这里也不太需要关心这个,知道有这么回事就可以了。

我们继续往下看 createProxy(…) 方法:

  1. // 注意看这个方法的几个参数,
  2. // 第三个参数携带了所有的 advisors
  3. // 第四个参数 targetSource 携带了真实实现的信息
  4. protected Object createProxy(
  5. Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
  6. if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
  7. AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
  8. }
  9. // 创建 ProxyFactory 实例
  10. ProxyFactory proxyFactory = new ProxyFactory();
  11. proxyFactory.copyFrom(this);
  12. // 在 schema-based 的配置方式中,我们介绍过,如果希望使用 CGLIB 来代理接口,可以配置
  13. // proxy-target-class="true",这样不管有没有接口,都使用 CGLIB 来生成代理:
  14. // <aop:config proxy-target-class="true">......</aop:config>
  15. if (!proxyFactory.isProxyTargetClass()) {
  16. if (shouldProxyTargetClass(beanClass, beanName)) {
  17. proxyFactory.setProxyTargetClass(true);
  18. }
  19. else {
  20. // 点进去稍微看一下代码就知道了,主要就两句:
  21. // 1. 有接口的,调用一次或多次:proxyFactory.addInterface(ifc);
  22. // 2. 没有接口的,调用:proxyFactory.setProxyTargetClass(true);
  23. evaluateProxyInterfaces(beanClass, proxyFactory);
  24. }
  25. }
  26. // 这个方法会返回匹配了当前 bean 的 advisors 数组
  27. // 对于本文的例子,"userServiceImpl" 和 "OrderServiceImpl" 到这边的时候都会返回两个 advisor
  28. // 注意:如果 specificInterceptors 中有 advice 和 interceptor,它们也会被包装成 advisor,进去看下源码就清楚了
  29. Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
  30. for (Advisor advisor : advisors) {
  31. proxyFactory.addAdvisor(advisor);
  32. }
  33. proxyFactory.setTargetSource(targetSource);
  34. customizeProxyFactory(proxyFactory);
  35. proxyFactory.setFrozen(this.freezeProxy);
  36. if (advisorsPreFiltered()) {
  37. proxyFactory.setPreFiltered(true);
  38. }
  39. return proxyFactory.getProxy(getProxyClassLoader());
  40. }

我们看到,这个方法主要是在内部创建了一个 ProxyFactory 的实例,然后 set 了一大堆内容,剩下的工作就都是这个 ProxyFactory 实例的了,通过这个实例来创建代理: getProxy(classLoader)

ProxyFactory 详解

根据上面的源码,我们走到了 ProxyFactory 这个类了,我们到这个类来一看究竟。

顺着上面的路子,我们首先到 ProxyFactory#getProxy(classLoader) 方法:

  1. public Object getProxy(ClassLoader classLoader) {
  2. return createAopProxy().getProxy(classLoader);
  3. }

该方法首先通过 createAopProxy() 创建一个 AopProxy 的实例:

  1. protected final synchronized AopProxy createAopProxy() {
  2. if (!this.active) {
  3. activate();
  4. }
  5. return getAopProxyFactory().createAopProxy(this);
  6. }

创建 AopProxy 之前,我们需要一个 AopProxyFactory 实例,然后看 ProxyCreatorSupport 的构造方法:

  1. public ProxyCreatorSupport() {
  2. this.aopProxyFactory = new DefaultAopProxyFactory();
  3. }

这样就将我们导到 DefaultAopProxyFactory 这个类了,我们看它的 createAopProxy(…) 方法:

  1. public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
  2. @Override
  3. public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
  4. // (我也没用过这个optimize,默认false) || (proxy-target-class=true) || (没有接口)
  5. if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
  6. Class<?> targetClass = config.getTargetClass();
  7. if (targetClass == null) {
  8. throw new AopConfigException("TargetSource cannot determine target class: " +
  9. "Either an interface or a target is required for proxy creation.");
  10. }
  11. // 如果要代理的类本身就是接口,也会用 JDK 动态代理
  12. // 我也没用过这个。。。
  13. if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
  14. return new JdkDynamicAopProxy(config);
  15. }
  16. return new ObjenesisCglibAopProxy(config);
  17. }
  18. else {
  19. // 如果有接口,会跑到这个分支
  20. return new JdkDynamicAopProxy(config);
  21. }
  22. }
  23. // 判断是否有实现自定义的接口
  24. private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
  25. Class<?>[] ifcs = config.getProxiedInterfaces();
  26. return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
  27. }
  28. }

到这里,我们知道 createAopProxy 方法有可能返回 JdkDynamicAopProxy 实例,也有可能返回 ObjenesisCglibAopProxy 实例,这里总结一下:

如果被代理的目标类实现了一个或多个自定义的接口,那么就会使用 JDK 动态代理,如果没有实现任何接口,会使用 CGLIB 实现代理,如果设置了 proxy-target-class=”true”,那么都会使用 CGLIB。

JDK 动态代理基于接口,所以只有接口中的方法会被增强,而 CGLIB 基于类继承,需要注意就是如果方法使用了 final 修饰,或者是 private 方法,是不能被增强的。

有了 AopProxy 实例以后,我们就回到这个方法了:

  1. public Object getProxy(ClassLoader classLoader) {
  2. return createAopProxy().getProxy(classLoader);
  3. }

我们分别来看下两个 AopProxy 实现类的 getProxy(classLoader) 实现。

JdkDynamicAopProxy 类的源码比较简单,总共两百多行,

  1. @Override
  2. public Object getProxy(ClassLoader classLoader) {
  3. if (logger.isDebugEnabled()) {
  4. logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
  5. }
  6. Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
  7. findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
  8. return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
  9. }

java.lang.reflect.Proxy.newProxyInstance(…) 方法需要三个参数,第一个是 ClassLoader,第二个参数代表需要实现哪些接口,第三个参数最重要,是 InvocationHandler 实例,我们看到这里传了 this,因为 JdkDynamicAopProxy 本身实现了 InvocationHandler 接口。

InvocationHandler 只有一个方法,当生成的代理类对外提供服务的时候,都会导到这个方法中:

  1. public interface InvocationHandler {
  2. public Object invoke(Object proxy, Method method, Object[] args)
  3. throws Throwable;
  4. }

下面来看看 JdkDynamicAopProxy 对其的实现:

  1. @Override
  2. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  3. MethodInvocation invocation;
  4. Object oldProxy = null;
  5. boolean setProxyContext = false;
  6. TargetSource targetSource = this.advised.targetSource;
  7. Class<?> targetClass = null;
  8. Object target = null;
  9. try {
  10. if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
  11. // The target does not implement the equals(Object) method itself.
  12. // 代理的 equals 方法
  13. return equals(args[0]);
  14. }
  15. else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
  16. // The target does not implement the hashCode() method itself.
  17. // 代理的 hashCode 方法
  18. return hashCode();
  19. }
  20. else if (method.getDeclaringClass() == DecoratingProxy.class) {
  21. // There is only getDecoratedClass() declared -> dispatch to proxy config.
  22. //
  23. return AopProxyUtils.ultimateTargetClass(this.advised);
  24. }
  25. else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
  26. method.getDeclaringClass().isAssignableFrom(Advised.class)) {
  27. // Service invocations on ProxyConfig with the proxy config...
  28. return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
  29. }
  30. Object retVal;
  31. // 如果设置了 exposeProxy,那么将 proxy 放到 ThreadLocal 中
  32. if (this.advised.exposeProxy) {
  33. // Make invocation available if necessary.
  34. oldProxy = AopContext.setCurrentProxy(proxy);
  35. setProxyContext = true;
  36. }
  37. // May be null. Get as late as possible to minimize the time we "own" the target,
  38. // in case it comes from a pool.
  39. target = targetSource.getTarget();
  40. if (target != null) {
  41. targetClass = target.getClass();
  42. }
  43. // Get the interception chain for this method.
  44. // 创建一个 chain,包含所有要执行的 advice
  45. List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
  46. // Check whether we have any advice. If we don't, we can fallback on direct
  47. // reflective invocation of the target, and avoid creating a MethodInvocation.
  48. if (chain.isEmpty()) {
  49. // We can skip creating a MethodInvocation: just invoke the target directly
  50. // Note that the final invoker must be an InvokerInterceptor so we know it does
  51. // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
  52. // chain 是空的,说明不需要被增强,这种情况很简单
  53. Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
  54. retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
  55. }
  56. else {
  57. // We need to create a method invocation...
  58. // 执行方法,得到返回值
  59. invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
  60. // Proceed to the joinpoint through the interceptor chain.
  61. retVal = invocation.proceed();
  62. }
  63. // Massage return value if necessary.
  64. Class<?> returnType = method.getReturnType();
  65. if (retVal != null && retVal == target &&
  66. returnType != Object.class && returnType.isInstance(proxy) &&
  67. !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
  68. // Special case: it returned "this" and the return type of the method
  69. // is type-compatible. Note that we can't help if the target sets
  70. // a reference to itself in another returned object.
  71. retVal = proxy;
  72. }
  73. else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
  74. throw new AopInvocationException(
  75. "Null return value from advice does not match primitive return type for: " + method);
  76. }
  77. return retVal;
  78. }
  79. finally {
  80. if (target != null && !targetSource.isStatic()) {
  81. // Must have come from TargetSource.
  82. targetSource.releaseTarget(target);
  83. }
  84. if (setProxyContext) {
  85. // Restore old proxy.
  86. AopContext.setCurrentProxy(oldProxy);
  87. }
  88. }
  89. }

上面就三言两语说了一下,感兴趣的读者自己去深入探索下,不是很难。简单地说,就是在执行每个方法的时候,判断下该方法是否需要被一次或多次增强(执行一个或多个 advice)。

说完了 JDK 动态代理 JdkDynamicAopProxy#getProxy(classLoader),我们再来瞄一眼 CGLIB 的代理实现 ObjenesisCglibAopProxy#getProxy(classLoader)。

ObjenesisCglibAopProxy 继承了 CglibAopProxy,而 CglibAopProxy 继承了 AopProxy。

ObjenesisCglibAopProxy 使用了 Objenesis 这个库,和 cglib 一样,我们不需要在 maven 中进行依赖,因为 spring-core.jar 直接把它的源代码也搞过来了。


通过 CGLIB 生成代理的代码量有点大,我们就不进行深入分析了,我们看下大体的骨架。它的 getProxy(classLoader) 方法在父类 CglibAopProxy 类中:

// CglibAopProxy#getProxy(classLoader)

  1. @Override
  2. public Object getProxy(ClassLoader classLoader) {
  3. ...
  4. // Configure CGLIB Enhancer...
  5. Enhancer enhancer = createEnhancer();
  6. if (classLoader != null) {
  7. enhancer.setClassLoader(classLoader);
  8. if (classLoader instanceof SmartClassLoader &&
  9. ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
  10. enhancer.setUseCache(false);
  11. }
  12. }
  13. enhancer.setSuperclass(proxySuperClass);
  14. enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
  15. enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
  16. enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
  17. Callback[] callbacks = getCallbacks(rootClass);
  18. Class<?>[] types = new Class<?>[callbacks.length];
  19. for (int x = 0; x < types.length; x++) {
  20. types[x] = callbacks[x].getClass();
  21. }
  22. // fixedInterceptorMap only populated at this point, after getCallbacks call above
  23. enhancer.setCallbackFilter(new ProxyCallbackFilter(
  24. this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
  25. enhancer.setCallbackTypes(types);
  26. // Generate the proxy class and create a proxy instance.
  27. return createProxyClassAndInstance(enhancer, callbacks);
  28. }
  29. catch (CodeGenerationException ex) {
  30. ...
  31. }
  32. catch (IllegalArgumentException ex) {
  33. ...
  34. }
  35. catch (Throwable ex) {
  36. ...
  37. }
  38. }

CGLIB 生成代理的核心类是 Enhancer 类,这里就不展开说了。

基于注解的 Spring AOP 源码分析

上面我们走马观花地介绍了使用 DefaultAdvisorAutoProxyCreator 来实现 Spring AOP 的源码,这里,我们也同样走马观花地来看下 @AspectJ 的实现原理。

我们之前说过,开启 @AspectJ 的两种方式,一个是 <aop:aspectj-autoproxy/>,一个是 @EnableAspectJAutoProxy,它们的原理是一样的,都是通过注册一个 bean 来实现的。

解析 <aop:aspectj-autoproxy/> 需要用到 AopNamespaceHandler:

4

然后到类 AspectJAutoProxyBeanDefinitionParser:

  1. class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {
  2. @Override
  3. @Nullable
  4. public BeanDefinition parse(Element element, ParserContext parserContext) {
  5. AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
  6. extendBeanDefinition(element, parserContext);
  7. return null;
  8. }
  9. ...
  10. }

进去 registerAspectJAnnotationAutoProxyCreatorIfNecessary(…) 方法:

  1. public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
  2. ParserContext parserContext, Element sourceElement) {
  3. BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
  4. parserContext.getRegistry(), parserContext.extractSource(sourceElement));
  5. useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
  6. registerComponentIfNecessary(beanDefinition, parserContext);
  7. }

再进去 AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary(…):

  1. public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,
  2. @Nullable Object source) {
  3. return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
  4. }

最终我们看到,Spring 注册了一个 AnnotationAwareAspectJAutoProxyCreator 的 bean,beanName 为:”org.springframework.aop.config.internalAutoProxyCreator”。

我们看下 AnnotationAwareAspectJAutoProxyCreator 的继承结构:

和前面介绍的 DefaultAdvisorAutoProxyCreator 一样,它也是一个 BeanPostProcessor,剩下的我们就不说了,它和它的父类 AspectJAwareAdvisorAutoProxyCreator 都不复杂。

闲聊 InstantiationAwareBeanPostProcessor

为什么要说这个呢?因为我发现,很多人都以为 Spring AOP 是通过这个接口来作用于 bean 生成代理的。

  1. public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
  2. Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;
  3. boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;
  4. PropertyValues postProcessPropertyValues(
  5. PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException;
  6. }

它和 BeanPostProcessor 的方法非常相似,而且它还继承了 BeanPostProcessor。

不仔细看还真的不好区分,下面是 BeanPostProcessor 中的两个方法:

  1. Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
  2. Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

发现没有,InstantiationAwareBeanPostProcessor 是 Instantiation,BeanPostProcessor 是 Initialization,它代表的是 bean 在实例化完成并且属性注入完成,在执行 init-method 的前后进行作用的。

而 InstantiationAwareBeanPostProcessor 的执行时机要前面一些,大家需要翻下 IOC 的源码:

  1. // AbstractAutowireCapableBeanFactory 447行
  2. protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
  3. ...
  4. try {
  5. // 让 InstantiationAwareBeanPostProcessor 在这一步有机会返回代理
  6. Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
  7. if (bean != null) {
  8. return bean;
  9. }
  10. }
  11. // BeanPostProcessor 是在这里面实例化后才能得到执行
  12. Object beanInstance = doCreateBean(beanName, mbdToUse, args);
  13. ...
  14. return beanInstance;
  15. }

点进去看 resolveBeforeInstantiation(beanName, mbdToUse) 方法,然后就会导到 InstantiationAwareBeanPostProcessor 的 postProcessBeforeInstantiation 方法,对于我们分析的 AOP 来说,该方法的实现在 AbstractAutoProxyCreator 类中:

  1. @Override
  2. public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
  3. ...
  4. if (beanName != null) {
  5. TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
  6. if (targetSource != null) {
  7. this.targetSourcedBeans.add(beanName);
  8. Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
  9. Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
  10. this.proxyTypes.put(cacheKey, proxy.getClass());
  11. return proxy;
  12. }
  13. }
  14. return null;
  15. }

我们可以看到,这里也有创建代理的逻辑,以至于很多人会搞错。确实,这里是有可能创建代理的,但前提是对于相应的 bean 我们有自定义的 TargetSource 实现,进到 getCustomTargetSource(…) 方法就清楚了,我们需要配置一个 customTargetSourceCreators,它是一个 TargetSourceCreator 数组。

这里就不再展开说 TargetSource 了,请参考 Spring Reference 中的 Using TargetSources

小结

本文真的是走马观花,和我之前写的文章有很大的不同,希望读者不会嫌弃。

(全文完)

转自:https://javadoop.com/post/spring-aop-source

 19

啊!这个可能是世界上最丑的留言输入框功能~


当然,也是最丑的留言列表

有疑问发邮件到 : suibibk@qq.com 侵权立删
Copyright : 个人随笔   备案号 : 粤ICP备18099399号-2