六。Spring之AOP(一)

Spring在xml中开启AOP:

<aop:aspectj-autoproxy />

在自定义标签注解解析时:

public void init(){

	registerBeanDefinitionParser("config",new ConfigBeanDefinitionParser());
	//注册AspectJ的解析器,一旦使用aspectj-autoproxy注解,就使用该解析器来解析
	registerBeanDefinitionParser("aspectj-autoproxy",new AspectJAutoProxyBeanDefinitionParser());

	......

}

所有的解析器都是对BeanDefinitionParser接口的统一实现,所以入口函数都是从parse方法开始的:

public BeanDefinition parse(Element element,ParserContext parserContext){
	//注册AspectJAnnotationAutoProxyCreator
	AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext,element);
	
	//对于注解中子类的处理
	extendBeanDefiniton(element,parserContext);
	return null
}

其中这个方法registerAspectJAnnotationAutoProxyCreatorIfNecessary是非常重要的,也是关键的逻辑实现

1.注册或者升级AnnotationAwareAspectJAutoProxyCreator:
AOP功能基本上都是由AnnotationAwareAspectJAutoProxyCreator来实现的,它可以根据@Point注解定义的切点来自动代理与其匹配的bean

2.处理proxy-tatget-class属性和expose-proxy属性

proxy-tatget-class:与使用哪种动态代理技术有关。如果需要代理的对象实现了至少一种接口,则使用jdk动态代理,反之使用cglib。

补:CGLIB和JDK动态代理:
	JDK:在运行期间创建接口的实现类实现动态代理
	CGLIB:在运行期间操作字节码从而针对目标类创建其子类

如果强制使用CGLIB的动态代理:

1.无法增强final方法,因为final方法不能够被子类实现覆盖
2.需要把CGLIB的包放到classPath下面
3.需要将<aop:config>标签的proxy-tatget-class属性设为true:
		<aop:config proxy-tatget-class="true" />

如果在目标对象中实现自我调用:

public interface TService{
	public void a();
	public void b();
}

@Service
public class TServiceImpl implements TService{
	@Transactional(...)
	public void a(){
		//在这里由于this指向了目标对象而不是代理对象
		//因此在执行这个自我调用时会调用自身的b方法而不是代理对象的b方法
		//所以在b方法上的事务切面不会被调用,即不会进行事务增强
		this.b();
	}
	
	@Transactional(...)
	public void b(){
		...
	}
}

上述问题解决办法:

<aop:aspectj-autoproxy expose-proxy = "true">

并将this.b()改成((AService)AopContext.currentProxy()).b(),这样就可以在自我调用中实现b方法的增强

猜你喜欢

转载自blog.csdn.net/xkshihaoren/article/details/88084256