美文网首页
最简单的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