原创

探秘Spring AOP(上)

SpringAOP

主要注解:

  • @Aspect
  • @Pointcut
  • Advice

Point express:切面表达式

designators : 指示器:描述通过什么样的方式匹配想要的类的什么方法

  • 匹配方法:使用通配符把执行的方法拦截下来

    • execution()

      • //匹配任何以find开头而且只有一个Long参数的方法
        @Pointcut("execution(* *..find*(Long))")
        public void argsDemo1(){}
        
      • //匹配任何以find开头而且第一个参数为Long的方法
        @Pointcut("execution(* *..find*(Long,..))")
        public void argsDemo3(){}
        
  • 匹配注解:标注service类下面的所有的方法,在方法上面有指定注解的方法,方法里面有一个参数,是某一个类,而该类有指定注解,可以筛选

    • @target():

      • //匹配标注右Repository的类地下的方法,要求annotation的RetentionPolicy级别为RUNTIME
        @Pointcut("@target(org.springframework.stereotye.Repository)")
        public void annoTargetDemo(){}
        
    • @args():

      • //匹配传入的参数类标注右Repository注解的方法
        @Pointcut("@args(org.springframework.stereotype.Repository)")
        public void annoArgsDemo(){}
        
    • @within():

      • //匹配标注右Beta的类底下的方法,要求的annotation的RetentionPolicy级别为CLASS
        @Pointcut("@within(com.google.common.annotations.Beta)")
        public void annoWithinDemo(){}
        
    • @annotation():

      • //匹配方法标注右AdminOnly的注解的方法
        @Pointcut("@annotation(com.debuggg.demo.security.AdminOnly)")
        public void annoDemo(){}
        
  • 匹配包/类型:匹配指定的包,类型及其子类

    • within()

      • //匹配ProductService类里面的所有方法
        @Pointcout("within(com.debuggg.service.ProductService)")
        public void matchType(){}
        
      • //匹配com.debuggg包及其子包下所有类的方法
        @Pointcut("within(com.debuggg..*)")
        
  • 匹配对象:匹配指定对象,匹配spring托管的指定对象

    • this()

      • //匹配AOP对象的目标对象为指定类型的方法,即DemoDao的aop代理对象的方法,其实就是实现该类的所有的方法
        //即目标对象的代理对象
        @Pointcut("this(com.debuggg.DemoDao)")
        public void thisDemo(){}
        
    • bean()

      • //匹配所有以Service结尾的bean里面的方法
        @Pointcut("bean(*Service)")
        public void beanDemo(){}
        
    • target()

      • //匹配实现IDao接口的目标对象(而不是aop代理后的对象)的方法,这里即DemoDao的方法,其实就是实现该类的所有的方法
        @Pointcut("target(com.debuggg.IDao)")
        public void targetDemo(){}
        
  • 匹配参数:匹配方法的第一个参数是String类型的(例子)

    • args()

      • //匹配第一个参数为Long型的方法
        @Pointcut("args(Long,..)")
        public void argsDemo4(){}
        
      • //匹配任何只有一个Long参数的方法
        @Pointcut("args(Long)")
        public void argsDemo2(){}
        
        //匹配任何只有一个Long参数的方法而且是在某个子包下面
        @Pointcut("args(Long) && within(com.debuggg.service.*)")
        public void matchArgs(){}
        

wildcards 通配符

  • *:匹配任意数量的字符
  • ..:一般用于匹配任意数的子包或参数
  • +:匹配指定类及其子类

operators 操作符(逻辑)

  • &&:与
  • || :或
  • !:非
execution()表达式

格式:其中标注问号的表示可以省略

execution(

​ modifier-pattern?:修饰符

​ ret-type-pattern:返回值

​ declaring-type-pattern:描述包名

​ name-pattern(param-pattern):方法名(方法参数)

​ throws-pattern? :匹配方法抛出的异常

)

例如:

//匹配public类型任意返回值,拦截了com.debuggg.service包下以Service结尾的类的任意方法,以及任意参数
@Pointcut("execution(public * com.debuggg.service.*Service.*(..))" )
//匹配public类型任意返回值,拦截了com.debuggg.service包以及子包下以Service结尾的类的任意方法,以及任意参数
@Pointcut("execution(public * com.debuggg.service..*Service.*(..))" )
//匹配public类型任意返回值,拦截了com.debuggg.service包以及子包下以Service结尾的类的任意方法,以及任意参数,以及抛出了IllegalAccessException异常的方法
@Pointcut("execution(public * com.debuggg.service..*Service.*(..)) throws java.lang.IllegalAccessException" )
public void matchType(){}

@Before("matchType()")
public void test(){}

5种Advice注解

  • @Before,前置通知
  • @After(finally),后置通知,方法执行完之后
  • @AfterReturning,返回通知,成功执行之后
  • @AfterThrowing,异常通知,抛出异常之后
  • @Around,环绕通知

@Before:方法执行之前

    @Pointcut("@annotation(com.debuggg.apspecttest.AopAnnotationTest)")
    public void matchType(){}

    @Before("matchType()")
    public void before(){
        System.out.println();
        System.out.println("###before");
    }

After:方法执行之后

@After("matchType() && within(com.debuggg..*)")
public void afterDemo(){
    System.out.println("#################after aop by within");
}

@AfterReturning("matchType() && within(com.debuggg..*)")
public void afterReturning(){
    System.out.println("#################after aop by within");
}

@AfterThrowing("matchType() && within(com.debuggg..*)")
public void afterThrowing(){
    System.out.println("#################after aop by within");
}

@Around

    @Around("matchType() && within(com.debuggg..*)")
    public Object AfterThrowing(ProceedingJoinPoint pjp) throws Throwable{
        System.out.println("#############before");
        try{
            Object result = pjp.proceed(pjp.getArgs());
            System.out.println("###################return");
            return result;
        }catch (Throwable e){
            System.out.println("#################ex");
            throw e;
        }finally {
            System.out.println("##################after");
        }
    }

Advice中的参数及结果绑定

    @Before(value = "matchType() && within(com.debuggg..*) && args(userId)")
    public void before(JoinPoint joinPoint,Long userId){
        System.out.println("before ,args:" + userId);
    }


    @AfterReturning(value = "matchType() && within(com.debuggg..*)",returning = "returnValue")
    public void afterReturning(Object returnValue){
        if(returnValue != null){
            System.out.println("after return , result:" + returnValue)
        }
    }

AOP原理

动态代理:

JDK方式

参考:http://debuggg.com/article/209

cglib实现方式

被代理类的接口:

public interface Subject {
    void hello();
}

被代理类

public class RealSubject implements Subject {
    @Override
    public void hello() {
        System.out.println("hello");
    }
}

动态代理cglib类:

public class DemoMethodInterceptor implements MethodInterceptor {

    public Object getInstance(Object o){
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(o.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("before in cglib");
        Object result = null;
        try {
            result = methodProxy.invokeSuper(o, objects);
            System.out.println("after return");
        }catch (Exception e){
            System.out.println("ex: " + e.getMessage());
            throw e;
        }finally {
            System.out.println("after in cglib");
        }
        return result;
    }
}

测试类:

public class Client {
    public static void main(String[] args) {
        // Enhancer enhancer = new Enhancer();
        // enhancer.setSuperclass(RealSubject.class);
        // enhancer.setCallback(new DemoMethodInterceptor());
        // Subject subject = (Subject) enhancer.create();
        Subject subject = (Subject) new DemoMethodInterceptor().getInstance(new RealSubject());

        subject.hello();
    }
}

探秘Spring AOP(下) http://debuggg.com/article/263

正文到此结束
本文目录