使用注解方式实现aop

来源:互联网 发布:java 实现php的pack 编辑:程序博客网 时间:2024/06/08 16:49
首先,在 xml 配置文件中,加入 aop 的资源:

< beans xmlns= "http://www.springframework.org/schema/beans"

      xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"

      xmlns:context= "http://www.springframework.org/schema/context"

      xmlns:aop= "http://www.springframework.org/schema/aop"

      xsi:schemaLocation= "http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/aop
          http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
           http://www.springframework.org/schema/context
          http://www.springframework.org/schema/context/spring-context-2.5.xsd" >

     < aop:aspectj-autoproxy proxy-target-class = "true"/>
     

定义一个切片类:

package aop.test.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component ;
/**
 * 切面
 */
@Aspect @Component
public class MyInterceptor {

    @Pointcut( "execution (* output.test.impl..*(..))")   //括号里规定了目标对象的范围,第一个*表示函数的返回类型不限,第二个*表示此包和子包下的所有函数均可。第一个连续两点表示包含子包,第二个连续两点表示函数的参数不限。
    private void anyMethod() {} //声明一个切入点

    @Before ("anyMethod() && args(name)" )  // 如果函数的参数个数不为1,则不会执行此前置通知。括号里的 name,要和底下函数中参数名一致才行,否则报错。
    public void doAccessCheck(String name) {
        System. out.println( "前置通知:" + name );
    }
    @AfterReturning(pointcut= "anyMethod()",returning= "result")
    public void doAfterReturning(String result) {
        System. out.println( "后置通知:" + result );
    }
    @After( "anyMethod()")
    public void doAfter() {
        System. out.println( "最终通知" );
    }
    @AfterThrowing(pointcut= "anyMethod()",throwing= "e")
    public void doAfterThrowing(Exception e) {
        System. out.println( "例外通知:" + e );
    }

    @Around( "anyMethod()")
    public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
        //if(){//判断用户是否在权限

        System. out.println( "进入方法" );
        Object result = pjp.proceed();
        System. out.println( "退出方法" );
        //}

        return result;
    }

}

用 @Aspect 注解的类,表示里面定义了很多拦截器,对一些函数执行前、后等加入通知。然后用 @Component (或者在xml中声明<bean>) 加入到 Spring 容器中。
HelloBean.output() 函数:

      public void output() {
           System. out.println( "name="+ name);
     }

测试此切片类:

      public void test() {
           AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml" );
           Hello hb = (Hello) ctx.getBean( "helloBean");
            hb.output();
     }

输出:

前置通知:Gong
进入方法
name=Gong
最终通知
后置通知:null
退出方法

注意 退出方法 和 后置通知 的顺序。

语法细节:
@Pointcut 中

execution (java.lang.String output.test.impl..*(java.lang.String,..))

表示匹配返回类型为String的、且第一个参数为String类型(其余参数不作要求) 的函数。如果想要匹配返回类型不是void的,可以用

execution (!void output.test.impl..*(java.lang.String,..))

原创粉丝点击