第二个例子: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");
}
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就实现了把这些业务需求与系统需求分开来做。这种解决的方式也称代理机制。