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;
关注微信号,看文章,拿红包
网友评论