spring AOP使用

来源:互联网 发布:iphone6屏幕解锁软件 编辑:程序博客网 时间:2024/05/22 08:10

      Spring AOP 无需使用任何特殊命令对 Java 源代码进行编译,它采用运行时动态地、在内存中临时生成代理类的方式来生成 AOP 代理。但在性能上相比较于编译是增强的AOP框架(AspectJ )稍差些。反编译spring AOP目标类的字节码,是没有发生改变的!

       

    Spring AOP 大致执行流程:

                                                

        Spring  AOP的基本概念:

1.  目标对象 : 自己写的类,想要增强的类。

2.  AOP代理啊 : 经过代理的类,实现增强。由AOP框架生成。

3.  AOP代理方法 :  Advice + 目标方法 + Advice.

4.  Advice :  增强处理。

5.  pointcut : 切入点。

      配置spring AOP的三个基本要素:

1.  在目标方法的哪里织入(before、after、after turn、after throwing、around)。

2.  通过execution表达式,指定对哪个类的哪个方法进行织入。

3.  指定织入的代码。

示例代码:

目标类:

public class UserService {private UserDao dao;public void test() {System.out.println("test method run . . . ");}public void setDao(UserDao dao) {System.out.println("setDao method run . . . ");this.dao = dao;}public long getUserTotal() {System.out.println("getUserTotal method run . . . ");return 100;}public String getUserName(Integer id) {System.out.println("getUserName method run . . . ");if(id <= 0) {throw new NullPointerException("id不可以小于0");}return "haha";}}


before织入方法:

public class BeforeAdvice {public void check() {System.out.println("-------权限检查-------");}public void parameCheck(Integer arg) {System.out.println("--------权限检查,获得目标方法的参数:" + arg + "---------");}}

before配置:

<bean id="before" class="spring.demo.aop.advice.BeforeAdvice"/><aop:config><!-- 对【无返回值,无形参】的方法进行织入--><aop:pointcut id="widhoutR_withoutP" expression="execution(void spring.demo.service.UserService.test())"/><!-- 对【无返回值,有形参】的方法进行织入 --><aop:pointcut id="widhoutR_P" expression="execution(void spring.demo.service.UserService.setDao(spring.demo.dao.UserDao))" /><!-- 对【有返回值,无形参】的方法进行织入 --><aop:pointcut id="R_widhoutP" expression="execution(long spring.demo.service.UserService.getUserTotal())"/><!-- 对【有返回值,有形参】的方法进行织入指定方法 --><aop:pointcut id="R_P" expression="execution(String spring.demo.service.UserService.getUserName(Integer)) and args(arg)"/><aop:aspect ref="before"><aop:before method="check" pointcut-ref="widhoutR_withoutP"/><aop:before method="check" pointcut-ref="widhoutR_P"/><aop:before method="check" pointcut-ref="R_widhoutP"/><aop:before method="parameCheck" pointcut-ref="R_P"/></aop:aspect></aop:config>


poincut配置的3个位置,其作用域也不同:

           1.   在<aop:config>中。

           2.   在<aop:aspect>中。

           3.   在<aop:before pointcut="...">

after织入方法:

public class AfterAdvice {public void loginfo() {System.out.println("-------日志记录--------\n");}}
after织入配置:

<bean id="after" class="spring.demo.aop.advice.AfterAdvice"/><aop:config><!-- 对UserService类中的所有方法进行织入 --><aop:pointcut id="after_exe"expression="execution(* spring.demo.service.UserService.*(..))"/><aop:aspect ref="after"><aop:after method="loginfo" pointcut-ref="after_exe"/></aop:aspect></aop:config>

after throwing织入方法:
public class ExceptionAdvice {public void printNullPointerMessage(NullPointerException npe) {System.out.println("-------出空指针异常 : " + npe.getMessage() + "-------");}public void printMessage() {System.out.println("-------出异常-------");}}
after throwing配置:

<aop:config><aop:pointcut id="exception_exe" expression="execution(* spring.demo.service.UserService.*(..))"/><!--  对所有异常织入 --><aop:aspect ref="exception"><aop:after-throwing method="printMessage" pointcut-ref="exception_exe"/></aop:aspect> <!-- 对指定的异常throwing织入 --><aop:aspect ref="exception"><aop:after-throwing method="printNullPointerMessage" pointcut-ref="exception_exe" throwing="npe"/></aop:aspect></aop:config>

after returning织入方法:

public class ReturnAdvice {public void returning() {System.out.println("------对没有抛出异常,有返回值的方法织入---------");}//此方法的参数类型和目标方法的返回值类型要相同public void afterReturning(long userTotal) {System.out.println("------对没有抛出异常,返回值为long的方法织入---------");}}

after returning配置:

<bean id="returning" class="spring.demo.aop.advice.ReturnAdvice"/><aop:config><aop:pointcut id="returning_exe"expression="execution(* spring.demo.service.UserService.*(..))"/><aop:aspect ref="returning"><!-- 对所有返回值的方法织入 --><aop:after-throwing method="returning" pointcut-ref="returning_exe"/><!-- 对所有返回long类型的方法织入 --><aop:after-returning method="afterReturning" pointcut-ref="returning_exe" returning="userTotal"/></aop:aspect></aop:config>

around织入方法:

public class AroundAdvice {@SuppressWarnings({ "null" })public Object advice(ProceedingJoinPoint pj) throws Throwable {System.out.println("目标方法的签名 : " + pj.getSignature());Object[] args  = pj.getArgs();//可以获得目标方法的参数,也可以对其进行处理System.out.println("目标方法的原参数 : " + Arrays.toString(args));args[0] = (Integer)args[0] + 100;Object result;//可以决定是否执行目标方法if(args == null && args.length == 0) {result = pj.proceed();} else {result = pj.proceed(args);}//也可以对目标方法的返回值进行修改,但是必须要和原方法的返回值类型一样result = (String)result + " world " + Arrays.toString(args);System.out.println("目标方法执行结束");return result;}}

around配置:

<bean id="around" class="spring.demo.aop.advice.AroundAdvice"/><aop:config><aop:pointcut id="around_exe"expression="execution(* spring.demo.service.UserService.getUserName(..))"/><aop:aspect ref="around"><aop:around method="advice" pointcut-ref="around_exe"/></aop:aspect></aop:config>

0 0