基础性的知识点,参考:http://www.docin.com/p-650303600.html
什么是AOP
Aspect Oriented Programming 面向方面/切面编程
AOP的作用
实现组件的重复利用,将共通组件与目标对象解耦,改善程序结构,提高灵活性
相关概念
1.Aspect切面
2.JoinPoint连接点:切面组件在目标对象上作用的位置
3.Pointcut切入点:连接点的集合,采用表达式指定
4.Target Object目标对象
5.Advice通知:切面组件在连接点上执行的动作,如:方法调用前/后/前后
6.AutoProxy动态代理:采用AOP之后,容器返回代理对象,用户使用后,由代理对象调用切面组件和目标对象的功能
a.目标对象有接口采用JDK代理 b没有接口采用CGLIB代理
使用
1.引入Jar包
所需Jar包
aspectjrt.jar aspectjweaver.jar结合spring框架所需jar
<dependency> <groupId>aopalliance</groupId> <artifactId>aopalliance</artifactId> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> </dependency>
2.新建切面
切面只是普通的bean
例如:
public class OptLogger{ //前置方法 public void logger(){ System.out.println("记录日志"); } //后置方法 public void myafterReturing(Object retVal){ System.out.println("后置通知"+retVal); } //异常方法 public void myafterException(Exception ex){ System.out.println("--异常通知begin--"); ex.printStackTrace(); System.out.println("--异常通知end--"); } //最终通知 public void myafter(){ System.out.println("--最终通知--"); } }
3.配置文件
<!--注册切面--> <bean id = "optLogger" class="tarena.aop.OptLogger"></bean> <aop:config> <aop:pointcut id="servicepointcut" expression="execution(* tarena.service.*.*(..))" /> <!--前置通知--> <aop:aspect id="loggeraspect" ref="optLogger"> <aop:before method="logger" pointcut-ref="servicepointcut"/> </aop:aspect> <!--后置通知--> <aop:aspect id="loggeraspect" ref="optLogger"> <aop:after-returing method="myafterReturing" return="retVal" pointcut-ref="servicepointcut"/> </aop:aspect> <!--异常通知--> <aop:aspect id="loggeraspect" ref="optLogger"> <aop:after-thowing method="myafterException" throwing="ex" pointcut-ref="servicepointcut"/> </aop:aspect> <!--最终通知 不论是否发生异常都会执行--> <aop:aspect id="loggeraspect" ref="optLogger"> <aop:after method="myafter" pointcut-ref="servicepointcut"/> </aop:aspect> </aop:config>4.切入点表达式说明:
Pointcut可以有下列方式来定义或者通过&& || 和!的方式进行组合.
args() @args() execution() this() target() @target() within() @within() @annotation其中:其中execution 是用的最多的,其格式为:
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)throws-pattern?)
returning type pattern,name pattern, and parameters pattern是必须的.
ret-type-pattern
1.*表示任何返回值 2.全路径的类名等.
name-pattern:指定方法名 parameters pattern:指定方法参数(声明的类型)
1.(..)代表所有参数 2.(*)代表一个参数 3.(*,String)代表第一个参数为任何值,第二个为String类型.具体举例说明:
任意公共方法的执行: execution(public * *(..))
任何一个以“set”开始的方法的执行: execution(* set*(..))
AccountService 接口的任意方法的执行:execution(* com.xyz.service.AccountService.*(..))
定义在service包里的任意方法的执行:execution(* com.xyz.service.*.*(..))
定义在service包和所有子包里的任意类的任意方法的执行:execution(* com.xyz.service..*.*(..))
定义在pointcutexp包和所有子包里的JoinPointObjP2类的任意方法的执行: execution(* com.test.spring.aop.pointcutexp..JoinPointObjP2.*(..))")
*** > 最靠近(..)的为方法名, 靠近.*(..))的为类名或者接口名,如上例的JoinPointObjP2.*(..))
pointcutexp包里的任意类.
within(com.test.spring.aop.pointcutexp.*)
pointcutexp包和所有子包里的任意类.
within(com.test.spring.aop.pointcutexp..*)
实现了Intf接口的所有类,如果Intf不是接口,限定Intf单个类.
this(com.test.spring.aop.pointcutexp.Intf)
***> 当一个实现了接口的类被AOP的时候,用getBean方法必须cast为接口类型,不能为该类的类型.
带有@Transactional标注的所有类的任意方法.
@within(org.springframework.transaction.annotation.Transactional)
@target(org.springframework.transaction.annotation.Transactional)
带有@Transactional标注的任意方法.
@annotation(org.springframework.transaction.annotation.Transactional)
***> @within和@target针对类的注解,@annotation是针对方法的注解
参数带有@Transactional标注的方法.
@args(org.springframework.transaction.annotation.Transactional)
参数为String类型(运行是决定)的方法.
args(String)
Pointcut 可以通过Java注解和XML两种方式配置,如下所示: -- 待补