SpringAOP总结

AOP是Aspcet Oriented Programming,实质意思就是将一些横切逻辑结成模块然后插入到业务逻辑的周围,而不侵入业务逻辑的代码当中,现在我们来看看aop的一些术语:

(1)连接点(JoinPoint):Spring只支持方法连接点,在spring中,方法都可以作为连接点

(2)切点(Pointcut):具体执行业务逻辑的业务方法所在处,可以通过切点函数得到具体的切点

(3)增强(Advice):织入到目标类连接点上的一段代码,并且拥有方位信息(方位指的是在切点的前面还是后面的意思)

(4)目标对象(target):增强织入的目标对象

(5)引介(introduction):为类增加一些接口和属性

(6)织入(weaving):spring采用动态代理,在运行期织入增强

(7)代理(Proxy):融合了原类和增强产生的结果类

(8):切面(Aspect):切面由切点和增强组成,Spring就是实现将增强添加到切点所在的位置


之前说道beanPostProcessor对于实现aop起到了重要作用,这里我们可以看到,这是因为这个processor提供了一些可以自动代理创建器,帮助增强织入到目标对象中产生代理对象


好了,现在我们继续来看下,spring有4种定义切面的方式:

一.基于Advisor类的方式:增强必须实现对应的接口,内部使用一个proxyFactory来产生代理对象(由于使用的较少,所以在这里不给demo)

二.基于注解:

@Aspect
public class TestAspect {
	@Before("execution(* say(..))")
	public void say(){
		System.out.println("hi");
	}
}

<aop:aspectj-autoproxy/>
	<bean id="carTarget" class="com.yue.test.PrivateCar"/>
	<bean id="testAspect" class="com.yue.aspectj.TestAspect"/>

String path = "bao.xml";
		ApplicationContext ac = new ClassPathXmlApplicationContext(path);
		PrivateCar pc = (PrivateCar) ac.getBean("carTarget");
		pc.say();

因为在这里当你通过getBean得到的已经是代理对象,所以在使用say方法的时候,实质上是调用了代理对象的这个方法。

下面来看看切点函数:

下面来介绍三个常用的切点函数:execution(),within(),target()

(1):execution(* *To(..))

第一个*代表任意返回值的方法,第一个*到括号之前代表方法的名字,*号代表任意数目的字符,这里是一切以to为后缀的方法,..表示任意多个参数

(2)within(com.baobaotao.*)匹配baobaotao这个包中所有类中的所有方法(不包括子类)

within(com.baobaotao..*)匹配所有类所有方法包括子类

(3)target(com.baobaotao.waiter)所有这个类和其子类的所有方法都匹配


然后再继续看看切点函数的复合运算:

&&:表示要取两个范围的交集

||:表示要取两个范围的并集

!:表示要取两个范围的非集


命名切点:使切点可以重用

不过这里有一个bug,照理说当方法修饰符是public的时候其他包中的切面应该也是可以引用这个切点的,然而在实验中会出现error bind type的错误,这令人十分不解,望高手指教

demo:

@Before("Gg.talk()")
	public void say(){
		System.out.println("hi");
	}

public class Gg {
	/*
	 * 必须注意的是方法修饰符限定了这个切点的使用范围
	 */
	@Pointcut("execution(* say(..))")
	public void talk(){	
	}
	

}

还有特殊一点的环绕增强,可以用过一个proceedingJoinPoint对象访问连接点的信息

@Aspect
public class TestAspect {
	/*
	 * 值得注意的是在环绕增强中,必须显示的调用pjp.proceed()方法调用业务逻辑
	 */
	@Around("Gg.talk()")
	public void say(ProceedingJoinPoint pjp) throws Throwable{
		System.out.println("fdaf");
		pjp.proceed();
		System.out.println("what a spring!");
	}
}
三.基于schema定义切面(这也是我觉得最有美感的一种)

直接上demo:

<aop:config proxy-target-class="true">
		<aop:pointcut expression="execution(* *say(..))" id="point"/>
		
		<aop:aspect ref="greetingAdvice">
			<aop:before pointcut-ref="point" method="says"/>
		</aop:aspect>
	</aop:config>
	
	<bean id="greetingAdvice" class="com.yue.test.GreetingBeforeAdvice" />
	<bean id="carTarget" class="com.yue.test.PrivateCar"/>
	

<aop:config>表示在这里面定义的切面会自动织入目标对象产生代理对象,proxy-target-class表示使用jdk代理还是cglib代理

<aop:aspect>表示定义一个切面,ref表示这个切面引用的增强bean对象,里面的method表示织入这个增强bean中的哪个方法

<aop:pointcut>表示定义一个切点,切面可以使用pointcut-ref引用这个切点

注意的是当时环绕增强的时候,对应的方法要改为:

	public void says(ProceedingJoinPoint pjp) throws Throwable{
		System.out.println("ggg");
		pjp.proceed();






郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。