AOP的原理与实现


AOP基本原理

在上一篇文章Bean的创建与循环依赖的最后,提到了一个BeanPostProcessor,它的其中一个实现类是AbstractAutoProxyCreator,AOP就是通过这个后置处理器来实现的

当有循环依赖时,通过三级缓存的lambda表达式,调用getEarlyBeanReference获取AOP代理对象,代码如下:

public Object getEarlyBeanReference(Object bean, String beanName) {
   Object cacheKey = getCacheKey(bean.getClass(), beanName);
   this.earlyProxyReferences.put(cacheKey, bean);
   return wrapIfNecessary(bean, beanName, cacheKey);
}

如果没有循环依赖,则是按照常规流程,在bean初始化之后调用AbstractAutoProxyCreatorpostProcessAfterInitialization,代码如下:

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
   if (bean != null) {
      Object cacheKey = getCacheKey(bean.getClass(), beanName);
      if (this.earlyProxyReferences.remove(cacheKey) != bean) {
         return wrapIfNecessary(bean, beanName, cacheKey);
      }
   }
   return bean;
}

可以发现,这两个路径,最终都是调用了wrapIfNecessary

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
   if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
      return bean;
   }
   if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
      return bean;
   }
   if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
      this.advisedBeans.put(cacheKey, Boolean.FALSE);
      return bean;
   }

   // Create proxy if we have 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;
}

wrapIfNecessary中调用了createProxy创建代理对象,继续往下追踪,能找到如下图所示的代码:

从图中可以看到,这里有两个实现,一个是JDK动态代理,一个是Cglib代理。

那么到底应该用哪种呢?请看createAopProxy方法:

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
   if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
      Class<?> targetClass = config.getTargetClass();
      if (targetClass == null) {
         throw new AopConfigException("TargetSource cannot determine target class: " +
               "Either an interface or a target is required for proxy creation.");
      }
      // 如果是接口,或者是代理类
      if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
         return new JdkDynamicAopProxy(config);
      }
      return new ObjenesisCglibAopProxy(config);
   }
   else {
      return new JdkDynamicAopProxy(config);
   }
}

当被代理对象是接口,或者是代理类的时候,将会使用JDK代理。

接下来以JdkDynamicAopProxy为例,这个类实现了InvocationHandler接口,熟悉JDK动态代理的应该对这个接口不陌生

文章作者: 周君
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 周君 !
评论