美文网首页
最简单的Spring AOP教程|基于@AspectJ的AOP精

最简单的Spring AOP教程|基于@AspectJ的AOP精

作者: 黄二狗V | 来源:发表于2019-01-04 12:57 被阅读0次

    Spring除了支持Schema方式配置AOP,还支持注解方式,使用@AspectJ风格的切面声明。

    注解方式启用Spring AOP

    以下两种方式任选其一:

    • 若是你的项目基于XML配置的,在xml中添加
     <aop:aspectj-autoproxy/>
    
    • 若是项目基于全注解的,在配置类中添加注解@EnableAspectJAutoProxy
    @Configuration
    @EnableAspectJAutoProxy
    @ComponentScan(basePackages = "com.mmdet.learn.ssm.aop")
    public class AopConfig {
    }
    

    以上配置,自动为Spring容器中配置了@aspectJ切面的bean创建代理,织入切面。默认使用JDK动态代理。也可以使用如下方式,使用CGLib动态代理技术织入增强:

    xml方式:<aop:aspectj-autoproxy proxy-target-class="true"/>
    注解方式:@EnableAspectJAutoProxy(proxyTargetClass = true)
    

    声明切面

    使用@Aspect注解进行声明,代码如下

    @Aspect
    @Component
    public class OperateLogAspect {
    }
    

    @Aspect表示该类作为切面,如果不使用@Component注解,就需要在xml中声明该bean.

    声明切入点

    @AspectJ风格的命名切入点使用org.aspectj.lang.annotation包下的@Pointcut实现,方法返回类型必须是void类型。

    @Pointcut(value="切入点表达式", argNames = "参数名列表") 
    
    • value:指定切入点表达式
    • argNames:指定切入点方法参数列表参数名字,可以有多个用“,”分隔,这些参数将传递给通知方法同名的参数,一定要同名!
    • 被 @Pointcut注解的方法名就是切入点名字,可以使用该名字进行引用该切入点表达式
    @Aspect
    @Component
    public class OperateLogAspect {
        @Pointcut(value="execution(* com.mmdet.learn.ssm.aop.RoleServiceImpl.printRole(..)) && args(param1,param2)", argNames = "param1,param2")
        public void print(String param1,int param2 ){}
    }
    

    声明通知

    @AspectJ风格的声明通知也支持5种通知类型,所有注解基于使用org.aspectj.lang.annotation 包下:

    • 前置通知:@Before
    @Before(value = "切入点表达式或命名切入点", argNames = "参数列表参数名")
    
    • 后置通知:@After
    @After ( value="切入点表达式或命名切入点", argNames="参数列表参数名") 
    
    • 后置返回通知:@AfterReturning
    @AfterReturning( 
    value="切入点表达式或命名切入点", pointcut="切入点表达式或命名切入点",
     argNames="参数列表参数名", returning="返回值对应参数名") 
    
    • 异常通知:@AfterThrowing
    @AfterThrowing (
     value="切入点表达式或命名切入点",pointcut="切入点表达式或命名切入点", 
    argNames="参数列表参数名", throwing="异常对应参数名")
    
    • 环绕通知:@Around
    @Around ( value="切入点表达式或命名切入点", argNames="参数列表参数名")
    

    其中部分通知中有pointcut属性,同样是指定切入点表达式或命名切入点,如果指定了,将覆盖value属性指定的,pointcut具有高优先级

    看一个完整示例:

    @Aspect
    public class RoleAspect {
        @Pointcut("execution(* com.mmdet.learn.ssm.aop.RoleServiceImpl.printRole(..))")
        public void print(){}
    
        @Before("print()")
        public void before(){
            System.out.println("before ... ");
        }
    
        @After("print()")
        public void after(){
            System.out.println("before ... ");
        }
    
        @Around("print()")
        public void around(ProceedingJoinPoint joinPoint){
            System.out.println("around before ... ");
            try {
                joinPoint.proceed();
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
            System.out.println("around after ... ");
        }
    
        @AfterReturning("print()")
        public void afterReturning(){
            System.out.println("afterReturning ... ");
        }
        @AfterThrowing("print()")
        public void afterThrowing(){
            System.out.println("afterThrowing ... ");
        }
    }
    

    引入

    @AspectJ风格的引入声明在切面中使用org.aspectj.lang.annotation包下的@DeclareParents声明

    @DeclareParents( value=" AspectJ语法类型表达式", defaultImpl="引入接口的默认实现类") 
    private Interface interface;
    
    关注微信号,看文章,拿红包

    相关文章:
    最简单的Spring AOP教程|基于Schema的AOP精讲

    相关文章

      网友评论

          本文标题:最简单的Spring AOP教程|基于@AspectJ的AOP精

          本文链接:https://www.haomeiwen.com/subject/thkhrqtx.html