spring aop代理

代理对象在项目启动时生成 ,代理对象生成之后,就会被加入到单例缓冲池中。
而我们的目标对象只是作为代理对象的一个属性存在而已。也就是说,你无法在Spring 容器中直接找到目标对象,但是你可以在Spring 容器中直接找到代理对象。

实例化Bean的过程是在AbstractAutowireCapableBeanFactory的``doCreateBean方法中完成的。在属性依赖注入后(也就是执行完populateBean后 )。调用了initializeBean`方法。这个方法为Bean添加了后置处理器。

applyBeanPostProcessorsAfterInitialization方法来应用后置处理器。而在这个方法中,遍历了所有的BeanPostProcessor,并且调用了BeanPostProcessor的后置处理方法postProcessAfterInitialization。

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
  // 调用JDK的安全验证机制
  if (System.getSecurityManager() != null) {
    // 实现PrivilegedAction接口的匿名内部类
    AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
      invokeAwareMethods(beanName, bean);
      return null;
    }, getAccessControlContext());
  } else {
    // 为bean实例包装相关属性:如名称、类加载器、所属容器等。
    invokeAwareMethods(beanName, bean);
  }

  Object wrappedBean = bean;
  // 如果Bean定义不为null或者bean定义不是合成的.
  if (mbd == null || !mbd.isSynthetic()) {
    // 调用BeanPostProcessors后置处理器,在Bean初始化之前做一些处理
    wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
  }

  try {
    // 调用bean实例初始化方法。这个方法是在SpringBean定义配置文件中通过init-method属性指定的
    // xml配置和注解配置、JSR注解配置是一样的。
    invokeInitMethods(beanName, wrappedBean, mbd);
  } catch (Throwable ex) {...省略异常信息...}
  if (mbd == null || !mbd.isSynthetic()) {
    // 调用BeanPostProcessors后置处理器,在Bean初始化之后做一些处理
    // 此方法中aop的入口
    wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
  }
  return wrappedBean;
}

// bean实例 初始化之后执行
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
  throws BeansException {

  Object result = existingBean;
  for (BeanPostProcessor processor : getBeanPostProcessors()) {
    // 调用所有后置处理器额方法。
    Object current = processor.postProcessAfterInitialization(result, beanName);
    if (current == null) {
      return result;
    }
    result = current;
  }
  return result;
}

可以看出在其中调用了applyBeanPostProcessorsAfterInitialization方法来应用后置处理器。而在这个方法中,遍历了所有的BeanPostProcessor,并且调用了BeanPostProcessor的后置处理方法postProcessAfterInitialization。

上面刚说过,BeanPostProcessor的实现类由很多。完成AOP的类是AbstractAutoProxyCreator,所以只看这个类的postProcessAfterInitialization方法:
initializeBean:

// 如果子类将bean标识为要代理的bean,则使用已配置的侦听器创建代理
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
  if (bean != null) {
    Object cacheKey = getCacheKey(bean.getClass(), beanName);
    if (this.earlyProxyReferences.remove(cacheKey) != bean) {
      // core1 必要时包裹
      return wrapIfNecessary(bean, beanName, cacheKey);
    }
  }
  return bean;
}

在这里面调用了一个核心方法wrapIfNecessary,


```java
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
  // 如果beanName有长度。并且代理源beans包含这个beanName。就直接返回
  if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
    return bean;
  }

  // 判断是否需要代理这个Bean
  if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
    return bean;
  }

  // 如果是基础类,或者应该跳过的类,
  // 所谓isInfrastructureClass就是指,Advice,PointCut,Advisor
  if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
  }

  // Create proxy if we have advice.
  // 如果有通知,就创建代理。
  // 获取这个Bean的通知
  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;
}
//可以看到有一个createProxy创建代理对象。
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
								 @Nullable Object[] specificInterceptors, TargetSource targetSource) {
  ...省略不重要信息...
  // core1. 重代理工厂中获取代理对象。通过classLoader
  return proxyFactory.getProxy(getProxyClassLoader());
}

public Object getProxy(@Nullable ClassLoader classLoader) {
  // core1.
  return createAopProxy().getProxy(classLoader);
}

其中createAopProxy()方法,就是创建了了一个工厂,后面是调用工厂的getProxy来生产代理对象。

createAopProxy其实就是选择代理策略——使用JDK动态代理或是CGLIB动态代理。

@Override
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)) {
      // core1 JdkDynamicAopProxy
      return new JdkDynamicAopProxy(config);
    }
    // core2 ObjenesisCglibAopProxy
    return new ObjenesisCglibAopProxy(config);
  }
  else {
    // core1 JdkDynamicAopProxy
    return new JdkDynamicAopProxy(config);
  }
}

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
  if (logger.isTraceEnabled()) {
    logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
  }
  // 获取所有的代理接口
  Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
  findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
  return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

JDK动态代理很经典的调用了Proxy.newProxyInstance来创建代理对象。至于CGLIB同样也是返回的代理对象

返回代理的对象
至此,可以看出,如果Bean想要使用AOP增强,那么initializeBean方法实际上返回的是一个被代理过得Bean对象。initializeBean方法继续往高层返回对象到IoC容器中(也就是初始化Bean)。最后容器中放入的Bean就是实现了AOP理念的Bean对象。

​ 返回对象

​ ↓↓↓↓

initializeBean——————>doCreateBean——>createBean——>doGetBean——>getBean——>preInstantiateSingletons——>finishBeanFactoryInitialization——>refresh——>构造方法。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值