增强(advice)(插入的代码):增强是织入目标类连接点上的一段程序代码。在Spring中,增强除用于描述一段程序代码外,还拥有另一个和连接点相关的信息-执行点的的方法。结合执行点的方法信息和切点信息,AOP就可以找到特点的连接点。
由于我们在实际编码中,在有些情况下,我们会写大量的重复性代码,比如SpringMVX中的Session和事物,造成代码冗余,因为为了简化开发,我们通过使用Spring的AOP来解决这个问题。
举例:删除论坛帖子!
1、首先,我们创建一个方法性能监控类
/**
* 方法性能监控类(线程不安全)
*/
public class MethodPerformace {
private long begin; //方法执行开始系统时间
private long end; //方法执行结束系统时间
private String methodName; //方法名
//记录开始时间
public MethodPerformace(String name) {
this.methodName=name;
this.begin=System.currentTimeMillis();
}
//打印性能统计结果
public void printPerformace() {
end=System.currentTimeMillis();
long elapse=end-begin;
System.out.println(methodName+"方法执行耗时:"+elapse+"毫秒");
}
//重置性能监控
public void reset(String name) {
this.methodName=name;
this.begin=System.currentTimeMillis();
}
}
由于这个类是线程不安全的,所以我们需要用到ThreadLocal来转换一下
2、创建一个性能监控工具类:
/**
* 性能监控工具类
*/
public class PerformanceMonitor {
private static ThreadLocal<MethodPerformace> threadLocal=new ThreadLocal<MethodPerformace>();
private MethodPerformace methodPerformace=null;
//开始性能统计
public static void begin(String name) {
System.out.println("开始性能监控");
MethodPerformace methodPerformace=threadLocal.get();
//如果该类为空,就通过参数创建一个新的类
if(methodPerformace==null) {
methodPerformace=new MethodPerformace(name);
threadLocal.set(methodPerformace);
}else {
methodPerformace.reset(name);
}
}
//性能统计结果
public static void end() {
MethodPerformace methodPerformace=threadLocal.get();
if(methodPerformace!=null) {
//调用打印耗时方法
methodPerformace.printPerformace();
System.out.println("结束性能统计");
threadLocal.set(null);
}
}
}
3、定义两个论坛接口
/**
* 论坛业务类
*/
public interface IForumService {
//删除论坛帖子
public void removeTopic(int topicID) ;
//删除论坛版块
public void removeForun(int forumID);
}
4、创建业务实现类
/**
* 论坛业务实现类
*/
public class ForumServiceImpl implements IForumService{
@Override
public void removeTopic(int topicID) {
//通过方法名启动性能监控,方法后面是具体的操作
PerformanceMonitor.begin("com.zh.aop.ForumServiceImpl.removeTopic");
System.out.println("模拟通过ID删除论坛帖子:"+topicID);
try {
//设置了一个睡眠时间,没什么用
Thread.sleep(40);
} catch (Exception e) {
// TODO: handle exception
}
//监控结束
PerformanceMonitor.end();
}
@Override
public void removeForun(int forumID) {
//通过方法名启动性能监控,方法后面是具体的操作
PerformanceMonitor.begin("com.zh.aop.ForumServiceImpl.removeForun");
System.out.println("模拟通过ID删除论坛模块:"+forumID);
try {
//同样设置了一个睡眠时间,没什么用
Thread.sleep(200);
} catch (Exception e) {
// TODO: handle exception
}
//监控结束
PerformanceMonitor.end();
}
}
5、通过创建一个前置增强类来实现这个功能
这里需要实现一个接口:MethodBeforeAdvice,里面只有一个方法
/**
*前置增强实现类
*/
public class ForumServiceBeforeAdvice implements MethodBeforeAdvice{
/**
* 参数1、获取目标对象的方法
* 参数2、获取目标对象的方法参数
* 参数3、获取目标对象
*/
@Override
public void before(Method method, Object[] args, Object object) throws Throwable {
//插入代码
System.out.println("这是前置增强版块");
System.out.println("打印调用目标方法名:"+method.getName());
System.out.println("答应调用目标的参数:"+args[0]);
}
}
6、设置AOP配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- 增强目标类Bean(业务实现类) -->
<bean id="target" class="com.zh.aop.ForumServiceImpl" />
<!-- 前置增强Bean -->
<bean id="forumBefore" class="com.zh.aop.ForumServiceBeforeAdvice" />
<!-- 配置前置增强代理类Bean -->
<bean id="forumServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean" >
<!-- 设置代理接口 -->
<property name="proxyInterfaces" value="com.zh.aop.IForumService"></property>
<!-- 设置代理目标对象 -->
<property name="target" ref="target" />
<!-- 设置织入增强对象 -->
<property name="interceptorNames" value="forumBefore" />
</bean>
</beans>
7、创建测试类
public class ForumServiceTest {
public static void main(String[] args) {
//读取配置,获得应用上下文对象
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("com/zh/aop/springaop.xml");
IForumService forumServiceProxy=(IForumService) applicationContext.getBean("forumServiceProxy");
forumServiceProxy.removeForun(1);
forumServiceProxy.removeTopic(1);
}
}
运行结果: