第二个例子:AOP
编写目标类与切面类
public class Waiter{ public String greetTo(String name) { System.out.println("这是目标类 name="+name); return "erer"; } } public class SectionAdvice{ public void before(){ System.out.println("before"); }
扫描二维码关注公众号,回复:
28732 查看本文章
public void after(){ System.out.println("after"); } } |
Xml配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <!-- 目标类 --> <bean id="waiter" class="com.aop2.Waiter"/> <!-- 定义切面类 --> <bean id="sectionAdvice" class="com.aop2.SectionAdvice"/> <!-- 前置通知 --> <aop:config> <!-- 自动注入切面类 --> <aop:aspect ref="sectionAdvice"> <!-- 切点 --> <aop:pointcut id="service" expression="execution(* com.aop.Waiter.*(..))" /> <!-- execution(* com.aop2.*.*(..))" 第一个*代表所有的返回值类型 第二个*代表所有的类 第三个*代表类所有方法 最后一个..代表所有的参数。 --> <!-- 通知 --> <aop:before pointcut-ref="service" method="before" /> <aop:after pointcut-ref="service" method="after" /> </aop:aspect> </aop:config> </beans> |
前置通知(Before advice):在某连接点(JoinPoint)之前执行的通知,但这个通知不能阻止连接点前的执行。ApplicationContext中在<aop:aspect>里面使用<aop:before>元素进行声明。例如,TestAspect中的doBefore方法。
后置通知(After advice):当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。ApplicationContext中在<aop:aspect>里面使用<aop:after>元素进行声明。例如,ServiceAspect中的returnAfter方法,所以Teser中调用UserService.delete抛出异常时,returnAfter方法仍然执行。
环绕通知(Around advice):包围一个连接点的通知,类似Web中Servlet规范中的Filter的doFilter方法。可以在方法的调用前后完成自定义的行为,也可以选择不执行。ApplicationContext中在<aop:aspect>里面使用<aop:around>元素进行声明。例如,ServiceAspect中的around方法。
抛出异常后通知(After throwing advice):在方法抛出异常退出时执行的通知。ApplicationContext中在<aop:aspect>里面使用<aop:after-throwing>元素进行声明。例如,ServiceAspect中的returnThrow方法。
返回后通知(After return advice):在某连接点正常完成后执行的通知,不包括抛出异常的情况。ApplicationContext中在<aop:aspect>里面使用<after-returning>元素进行声明。
AOP术语:
AOP:Aspect Oriented Programing 的简称,翻译:面向切面编程
增强(Advice):增强是织入到目标连接点上的一段程序代码。
织入(Weaving):织入是将增强添加对目标具体连接点上的过程,AOP像一台织布机,将目标、增强通过AOP这台织布机天衣无缝地编织到一起。
连接点(joinpoint):程序执行的某个特定位置:如类开始初始化前、类初始化后、类某个方法调用前、调用后、方法抛出异常后。
切点:每个程序类都拥有多个连接点,如一个拥有两个方法的类,这两个方法都是连接点。但是这为数众多的连接点中,如何定位到某个感兴趣的连接点上呢?AOP通过”切点”定位特定连接点。一句话:切点就是指定的连接点。
代理:一个类被AOP织入增强后,将产生了一个结果类,它是融合了原类和增强逻辑的代理类。根据不同的代理方法,代理类既可能是和原类具有相同接口的类,也可能就是原类的子类,所以我们可以采用调用原类相同的方式调用代理类。
切面:切面由切点和增强组成,它既包括了增强的定义,也包括了连接点的定义。Spring AOP 就是负责实施切面的框架,它将切面所定义的增强织入到切点(指定的连接点)中。
为什么需要面向切面编程?
我们现在做的一些非业务,如:日志、事务、安全等都会写在业务代码中(也即是说,这些非业务类横切于业务类),但这些代码往往是重复,复制——粘贴式的代码会给程序的维护带来不便,AOP就实现了把这些业务需求与系统需求分开来做。这种解决的方式也称代理机制。