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