Spring AOP
Spring AOP(面向方面编程)框架,用于在模块化方面的横切关注点。
简单得说,它只是一个拦截器拦截一些过程,在方法执行之前或之后添加额外的功能。
API
实现一些spring aop的接口,来实现通知
有 4 种类型通知(advices)的支持:
- 通知(Advice)之前 - 该方法执行前运行
- 通知(Advice)返回之后 – 运行后,该方法返回一个结果
- 通知(Advice)抛出之后 – 运行方法抛出异常后
- 环绕通知 – 环绕方法执行运行,结合以上这三个通知
简单例子
public class People {
private String name;
private int age;
public void eat(){
System.out.println(name+ " 正在吃饭。。。。。。");
}
public void sleep(){
System.out.println(name + " 正在睡觉。。。。。");
}
public void doErrorThing() {
throw new IllegalArgumentException("做错事。。。。。");
}
@Override
public String toString() {
return String.format("姓名:%s <-> 年龄:%d", name,age);
}
.......
setter and getter
}
1、前置通知
实现:MethodBeforeAdvice 接口
org.springframework.aop.MethodBeforeAdvice
package com.wm.spring.AOP;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class PeopleMethodBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method arg0, Object[] arg1, Object arg2)
throws Throwable {
System.out.println("运行方法之前。。");
System.out.println("接下来将运行方法:"+arg0.getName());
}
}
spring.xml配置文件
<!-- Spring AOP -->
<bean id="people" class="com.wm.spring.IOC.People">
<property name="name" value="jack"/>
<property name="age" value="18" />
</bean>
<!-- 前向通知 -->
<bean id="methodBefore" class="com.wm.spring.AOP.PeopleMethodBeforeAdvice"></bean>
<bean id="methodBeforeProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="people" />
<property name="interceptorNames">
<list>
<value>methodBefore</value>
</list>
</property>
</bean>
测试结果:
@Test
public void TestSpringAOP(){
System.out.println("AOP");
People pp = (People)ac.getBean("methodBeforeProxy");
pp.eat();
pp.sleep();
pp.doErrorThing();
}
结果:
信息: Loading XML bean definitions from class path resource [spring.xml]
AOP
运行方法之前。。
接下来将运行方法:eat
jack 正在吃饭。。。。。。
运行方法之前。。
接下来将运行方法:sleep
jack 正在睡觉。。。。。
运行方法之前。。
接下来将运行方法:doErrorThing
2、后项通知
在方法执行之后 实现的一些方法
接口:
import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;
public class PeopleAfterRetureAdvice implements AfterReturningAdvice{
@Override
public void afterReturning(Object arg0, Method arg1, Object[] arg2,
Object arg3) throws Throwable {
System.out.println("刚刚执行了方法:"+arg1.getName());
System.out.println("方法返回之后。。。。");
}
}
配置文件:
<!-- 返回通知 -->
<bean id="afterReturn" class="com.wm.spring.AOP.PeopleAfterRetureAdvice"></bean>
<bean id="methodBeforeProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="people" />
<property name="interceptorNames">
<list>
<value>afterReturn</value>
</list>
</property>
</bean>
测试:
@Test
public void TestSpringAOP(){
System.out.println("AOP");
People pp = (People)ac.getBean("methodBeforeProxy");
pp.eat();
pp.sleep();
pp.doErrorThing();
}
结果:
信息: Loading XML bean definitions from class path resource [spring.xml]
AOP
jack 正在吃饭。。。。。。
刚刚执行了方法:eat
方法返回之后。。。。
jack 正在睡觉。。。。。
刚刚执行了方法:sleep
方法返回之后。。。。
3、抛出异常后通知
实现接口:ThrowsAdvice
org.springframework.aop.ThrowsAdvice
接口:
public class PeopleAfterThrowAdvice implements ThrowsAdvice{
public void afterThrowing(IllegalArgumentException e) throws Throwable {
System.out.println("抛出异常后 通知。。。。"+e);
}
}
这里实现的方法:afterThrowing ,它不是接口ThrowsAdvice中定义的方法,但是要实现抛出异常后通知就必须实现此方法,并且注意大小写。
还有就是这里捕获的异常IllegalArgumentException e ,要和发生异常相同
public void doErrorThing() {
throw new IllegalArgumentException("做错事。。。。。");
}
也可以用 Exception e 捕获所有的异常。
配置:
<!-- 抛出异常后通知 -->
<bean id="afterThrow" class="com.wm.spring.AOP.PeopleAfterThrowAdvice"></bean>
<bean id="methodBeforeProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="people" />
<property name="interceptorNames">
<list>
<value>afterThrow</value>
</list>
</property>
</bean>
测试结果:
信息: Loading XML bean definitions from class path resource [spring.xml]
AOP
jack 正在吃饭。。。。。。
jack 正在睡觉。。。。。
抛出异常后 通知。。。。java.lang.IllegalArgumentException: 做错事。。。。。
4、环绕通知
它结合了上面的三个通知,在方法执行过程中执行。创建一个实现了MethodInterceptor接口的类。
必须调用“MethodInvocation.proceed();” 继续在原来的方法执行,否则原来的方法将不会执行。
org.aopalliance.intercept.MethodInterceptor
接口:
public class PeopleAroundMethod implements MethodInterceptor{
@Override
public Object invoke(MethodInvocation arg0) throws Throwable {
System.out.println("method name: "+arg0.getMethod().getName());
System.out.println("arguments:"+arg0.getArguments());
System.out.println("method before .....");
Object obj = null ;
try {
obj = arg0.proceed();//让方法继续执行
System.out.println("method return after ......");
} catch (IllegalArgumentException e) {
System.out.println("throw after ...... "+e);
}
return obj;
}
}
配置文件:
<!-- 方法环绕通知 -->
<bean id="aroundMethod" class="com.wm.spring.AOP.PeopleAroundMethod"></bean>
<bean id="methodBeforeProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="people" />
<property name="interceptorNames">
<list>
<value>aroundMethod</value>
</list>
</property>
</bean>
测试结果:
信息: Loading XML bean definitions from class path resource [spring.xml]
AOP
method name: eat
arguments:[Ljava.lang.Object;@ab85b52
method before .....
jack 正在吃饭。。。。。。
method return after ......
method name: sleep
arguments:[Ljava.lang.Object;@ab85b52
method before .....
jack 正在睡觉。。。。。
method return after ......
method name: doErrorThing
arguments:[Ljava.lang.Object;@ab85b52
method before .....
throw after ...... java.lang.IllegalArgumentException: 做错事。。。。。
Spring AOP的实现,除了使用实现接口API方式以外,还有一种比较常用的方式–可以在spring.xml 中 使用XML aop约束配置来配置。
xmlns:aop="http://www.springframework.org/schema/aop"