最近忙于面试换工作,不论是学习还是工作似乎都忽略了spring另外的一个强大之处:AOP;当被面试问道如何基于AOP做出一个单点登录的时候顿时有点傻眼。下来之后做了一番学习。本文以日志管理为例,说明AOP的强大之处。
首先,说明一下AOP的强大应用。
可以简单实现强大的功能:日志记录,性能统计,安全控制,事物处理,异常处理等。
AOP是Aspect Oriented Programming ,意识是面向切面变成,实际是GoF设计模式的延续。
Aspect:切面,在AOP中可以采用@Aspect注解来实现切面
Joinpoint:连接点,在Spring AOP中一个连接点代表一个方法的执行。
Advice:通知,在切面(Aspect)的某个特定的连接点(Joinpoint)上执行的动作。通知有几种类型:
around:方法执行前后通知;
before:方法执行前通知;
after:方法执行后通知;
Pointcut:定义一个或一组方法,当是在这些方法时可以产生通知。
@AspectJ风格的AOP配置
Spring AOP配置有两种风格:
XML风格 = 采用声明形式实现Spring AOP
AspectJ风格 = 采用注解形式实现Spring AOP
注:本文采用XML风格
好了,开始我们的code。
首先搭建spring的配置在http://blog.csdn.net/upxiaofeng/article/details/38435531一文中阐述。
补充的是aop的xml配置:applicationContext.xml
<aop:aspectj-autoproxy />
<!-- 启用日志类 -->
<bean id="mylog" class="controller.log.MyLog"></bean>
<!-- AOP配置 proxy-target-class需要设置为true-->
<aop:config proxy-target-class="true">
<!-- expression 设置切入一个或者一组方法 -->
<aop:pointcut id="log" expression="execution(* service.*.*(..))" />
<!-- aspect 设置切面 -->
<aop:aspect id="myLog" ref="mylog">
<!-- before 方法执行之前通知,method:通知的方法 -->
<aop:before pointcut-ref="log" method="before"/>
<!-- after 方法执行之后通知,method:通知的方法 -->
<aop:after pointcut-ref="log" method="after"/>
</aop:aspect>
</aop:config>
MyLog的代码:
package controller.log;
import org.aspectj.lang.JoinPoint;
public class MyLog {
// 在类里面写方法,方法名诗可以任意的。此处我用标准的before和after来表示
// 此处的JoinPoint类可以获取,action所有的相关配置信息和request等内置对象。
public void before(JoinPoint joinpoint) {
// 此方法返回的是一个数组,数组中包括request以及ActionCofig等类对象
Object[] object = joinpoint.getArgs();
for(Object o:object){
System.out.println(o);
}
System.out.println(joinpoint.getClass().getMethods());
System.out.println(joinpoint.getTarget());
System.out.println("被拦截方法调用之前调用此方法,输出此语句");
}
public void after(JoinPoint joinpoint) {
System.out.println("被拦截方法调用之后调用此方法,输出此语句");
}
}
在执行service包里面的所有类的所有方法的时候会进入mylog中。
注:处理的时候可能会报错,是因为包重复原因是Spring中的cglib-nodep-2.1.3.jar与Hibernate中的cglib-2.2.jar相冲突!
我的解决方法是 删除cglib即可