Spring-AOP模块的ProxyConfig分析

描述:在Spring框架中,AOP模块是通过实现BeanPostProcessor相关类型与IOC模块集成的

UML结构图如下:

AbstractAdvisingBeanPostProcessor:BeanPostProcessor的基本实现,将一个Spring AOP advisor应用到多个spring bean

  属性:

@Nullable
protected Advisor advisor;

protected boolean beforeExistingAdvisors = false;

private final Map<Class<?>, Boolean> eligibleBeans = new ConcurrentHashMap<>(256);

  核心方法:

  1.postProcessBeforeInitialization  

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
	return bean;
}

  2.postProcessAfterInitialization

  

@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) {
		if (bean instanceof AopInfrastructureBean || this.advisor == null) {
			// Ignore AOP infrastructure such as scoped proxies.
			return bean;
		}

		if (bean instanceof Advised) {
			Advised advised = (Advised) bean;
			if (!advised.isFrozen() && isEligible(AopUtils.getTargetClass(bean))) {
				// Add our local Advisor to the existing proxy's Advisor chain...
				if (this.beforeExistingAdvisors) {
					advised.addAdvisor(0, this.advisor);
				}
				else {
					advised.addAdvisor(this.advisor);
				}
				return bean;
			}
		}

		if (isEligible(bean, beanName)) {
			ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName);
			if (!proxyFactory.isProxyTargetClass()) {
				evaluateProxyInterfaces(bean.getClass(), proxyFactory);
			}
			proxyFactory.addAdvisor(this.advisor);
			customizeProxyFactory(proxyFactory);
			return proxyFactory.getProxy(getProxyClassLoader());
		}

		// No async proxy needed.
		return bean;
	}

  

备注:

  1. 如果bean已经是Aop Proxy(advised)并且advisor能够应用到bean,将advisor添加到bean的advisor列表中

  2. 如果advisor能够应用到bean,根据当前配置初始化ProxyFactory,通过proxyFactory.getProxy创建Aop Proxy

辅助方法:

/**
	 * Check whether the given class is eligible for advising with this
	 * post-processor's {@link Advisor}.
	 * <p>Implements caching of {@code canApply} results per bean target class.
	 * @param targetClass the class to check against
	 * @see AopUtils#canApply(Advisor, Class)
	 */
	protected boolean isEligible(Class<?> targetClass) {
		Boolean eligible = this.eligibleBeans.get(targetClass);
		if (eligible != null) {
			return eligible;
		}
		if (this.advisor == null) {
			return false;
		}
		eligible = AopUtils.canApply(this.advisor, targetClass);
		this.eligibleBeans.put(targetClass, eligible);
		return eligible;
	}

 

/**
	 * Prepare a {@link ProxyFactory} for the given bean.
	 * <p>Subclasses may customize the handling of the target instance and in
	 * particular the exposure of the target class. The default introspection
	 * of interfaces for non-target-class proxies and the configured advisor
	 * will be applied afterwards; {@link #customizeProxyFactory} allows for
	 * late customizations of those parts right before proxy creation.
	 * @param bean the bean instance to create a proxy for
	 * @param beanName the corresponding bean name
	 * @return the ProxyFactory, initialized with this processor's
	 * {@link ProxyConfig} settings and the specified bean
	 * @since 4.2.3
	 * @see #customizeProxyFactory
	 */
	protected ProxyFactory prepareProxyFactory(Object bean, String beanName) {
		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.copyFrom(this);
		proxyFactory.setTarget(bean);
		return proxyFactory;
	}

AbstractAutoProxyCreator:BeanPostProcessor实现类,使用AOPProxy(添加对应的拦截器列表)包装符合条件的bean

AbstractAutoProxyCreator区分了不同的拦截器种类。“公共”拦截器:被它创建的所有代理共享; “特定”拦截器:每个bean instance使用独立的拦截器(interceptorNames属性区分)

子类可以应用任何策略来决定是否要对bean进行代理,例如通过类型、名称、定义细节等。它们还可以返回只应用于特定bean实例的额外拦截器。使用TargetSource包装目标bean

UML结构图如下:

备注:getAdvicesAndAdvisorsForBean是抽象方法

核心方法:

1.postProcessBeforeInstantiation

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
   Object cacheKey = getCacheKey(beanClass, beanName);
   if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
      if (this.advisedBeans.containsKey(cacheKey)) {
         return null;
      }
      if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
         this.advisedBeans.put(cacheKey, Boolean.FALSE);
         return null;
      }
   }

   // Create proxy here if we have a custom TargetSource.
   // Suppresses unnecessary default instantiation of the target bean:
   // The TargetSource will handle target instances in a custom fashion.
   TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
   if (targetSource != null) {
      if (StringUtils.hasLength(beanName)) {
         this.targetSourcedBeans.add(beanName);
      }
      Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
      Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
      this.proxyTypes.put(cacheKey, proxy.getClass());
      return proxy;
   }
   return null;
}

 备注:通过实现Spring IOC模块的InstantiationAwareBeanPostProcessor接口的postProcessBeforeInstantiation方法,在Spring Bean对象初始化之前拦截生成Proxy。将AOP模块集成进IOC模块

2.createProxy

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()) {
      if (shouldProxyTargetClass(beanClass, beanName)) {
         proxyFactory.setProxyTargetClass(true);
      }
      else {
         evaluateProxyInterfaces(beanClass, proxyFactory);
      }
   }
   Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
   proxyFactory.addAdvisors(advisors);
   proxyFactory.setTargetSource(targetSource);
   customizeProxyFactory(proxyFactory);
   proxyFactory.setFrozen(this.freezeProxy);
   if (advisorsPreFiltered()) {
      proxyFactory.setPreFiltered(true);
   }
   return proxyFactory.getProxy(getProxyClassLoader());
}

 备注:proxyFactory.copyFrom(this) proxyFactory通过复制AbstractAutoProxyCreator的配置进行初始化,方便通过xml进行配置

 流程图如下:

AbstractAdvisorAutoProxyCreator:通用Proxy代理类,根据在Bean上监测到(使用beanfactory)的Advisors建立AOP Proxy

核心方法:

1.getAdvicesAndAdvisorsForBean(从AbstractAutoProxyCreator继承)

AdvisorAdapterRegistry:Spring AOP的内部使用接口,用来登记Advisor适配器。DefaultAdvisorAdapterRegistry具体实现登记Advisor适配器

UML结构图如下:

BeanNameAutoProxyCreator:通过名称列表(beanNames)筛选将bean标识为代理对象(proxy)

核心方法:

1.getAdvicesAndAdvisorsForBean 如果bean名称在配置的名称列表中,则将bean标示为代理(proxy)

DefaultAdvisorAutoProxyCreator:基本与AbstractAdvisorAutoProxyCreator一致,重写了isEligibleAdvisorBean方法

protected boolean isEligibleAdvisorBean(String beanName) {
   if (!isUsePrefix()) {
      return true;
   }
   String prefix = getAdvisorBeanNamePrefix();
   return (prefix != null && beanName.startsWith(prefix));
}

ProxyConfig:代理的基本配置的父类

UML结构图如下:

  

ProxyProcessorSupport:提供代理处理器通用功能的基类

UML类图结构如下:

核心方法:

1.evaluateProxyInterfaces

protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
   Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
   boolean hasReasonableProxyInterface = false;
   for (Class<?> ifc : targetInterfaces) {
      if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
            ifc.getMethods().length > 0) {
         hasReasonableProxyInterface = true;
         break;
      }
   }
   if (hasReasonableProxyInterface) {
      // Must allow for introductions; can't just set interfaces to the target's interfaces only.
      for (Class<?> ifc : targetInterfaces) {
         proxyFactory.addInterface(ifc);
      }
   }
   else {
      proxyFactory.setProxyTargetClass(true);
   }
}

备注:获取BeanClass类型所有接口并根据一定的规则进行筛选;

           a. 如果还有可用的接口,添加可用的接口到proxyFactory (JDK Dynamic Proxy)

           b.如果没有,设置proxyFactory的ProxyTargetClass属性为true (CGLIb Proxy

  

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值