Spring中对于代理类子类实例化时的代理创建问题

     在spring中,通常在进行事务处理时,我们都会写如一段事务配置文件来保证相应的service类被代理成受事务控制的。那么对于那些没有配置成事务的Service,spring是否也会创建相应的代理类,并且在某些方法上也会追加相应的事务呢。

     如下的一段配置:

<aop:config proxy-target-class="true">
		<aop:pointcut id="servicePointcut"
					  expression="execution(public * com.greejoy.gtip.component.support.service.BaseService.*(..))"/>
		<aop:advisor advice-ref="txInterceptor" pointcut-ref="servicePointcut"/>
	</aop:config>

    我们配置了对于在包com.greejoy.gtip.component.support.service下的BaseService类的任何方法均配置一个pointcut,也就是说在这个BaseService下的任何方法均会被拦截,并会通知txInterceptor进行处理。在我们的txInterceptor中处理代码,即打印一句话,表示进入了这个拦截器:

public Object invoke(MethodInvocation invocation) throws Throwable {
		System.out.println("----222");
		return invocation.proceed();
	}

    现在,我们有一个测试类,用于测试指定的类是否已经被spring代理:

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
Tx2 tx2 = (Tx2) applicationContext.getBean("tx2");
System.out.println(tx2.getClass());

    其中类Tx2的声明如下:

public class Tx2 extends BaseService

    即Tx2是继承于BaseService的,上面一段代码的输出结果会根据一些变化有所不同。具体描述如下:

  1.  如果BaseService中没有任何方法(即只是一个标志类),BaseService中没有方法满足我们所声明的pointcut,那么输出结果将会输出class Tx2,表示Tx2没有被spring代理。
  2.  如果BaseService中有至少一个方法(即使这个方法是ovveride Object类的hascode方法),即可以满足声明中的pointcut,那么输出结果将会输出class Tx2$cglibGeneXXX这样的字样,表示这个Tx2类已经被代理了。

     为什么会出现这样的结果,这得归结于spring对于一个bean在初始化时是否应该创建代理的判断了。如下一段代码,spring在创建一个bean之后,会通知beanPostProcessor类来对这个bean作一些附加的处理,其中就会有AspectJAwareAdvisorAutoProxyCreator这个类。这个类会判断当前判断的类是否应该进行创建代理,以及给该对象创建代理。是否应该创建代理,就会根据当前spring容器中注册的pointcut和当前类进行判断,判断是否应该追加代理,相应的逻辑在类AopUtils的canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions)方法上:

MethodMatcher methodMatcher = pc.getMethodMatcher();
		IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
		……

		Set<Class> classes = new HashSet<Class>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
		classes.add(targetClass);
		for (Class<?> clazz : classes) {
			Method[] methods = clazz.getMethods();
			for (Method method : methods) {
				if ((introductionAwareMethodMatcher != null &&
						introductionAwareMethodMatcher.
matches(method, targetClass, hasIntroductions)) ||
						methodMatcher.matches(method, targetClass)) {
					return true;
				}
			}
		}

    如上的类,即会查找当前类的所有方法,并将这些方法和具体的pointcut进行对比,如果其中一个方法满足条件,即会创建代理了。

     那么我们来看现在的Tx2类,在BaseService没有方法的时候,Tx2的所有方法归纳如下:
 

     其中可以看出,在11个方法中并没有一个方法满足于pointcut的条件。而如果BaseService有一个方法呢,那么Tx2的所有方法就会有一点不一样了:

 

     这里的12个方法中,新增加了一个方法,为BaseService.x方法(即新增加的方法),这个方法的签名为BaseService.x,而并不是Tx2.x,那么这个签名肯定是满足我们的pointcut判断的(具体判断逻辑请参照相应代码),那么Tx2类就会被创建代理了。

     终上所述,对于并没有在pointcut中所直接满足条件的类,如果这些类的父类满足pointcut的断言判断的话,那么也会给这些类创建代理对象进行aop代理。那么这些创建好的对象的自己的方法是否也会受aop Interceptor的影响呢,那就关系到spring在代理创建过程中对方法一级代理的处理问题了。
    对于spring如何处理代理子类的代理方法的问题,请点击spring中aop对于非匹配子类方法拦截问题

转载请标明出处:i flym
本文地址:https://www.iflym.com/index.php/code/proxy-created-of-subclass-extended-proxied-class-by-spring.html

相关文章:

作者: flym

I am flym,the master of the site:)

发表评论

邮箱地址不会被公开。 必填项已用*标注