一、基于注解的通知
1.创建一个User类
@Component
public class User {
public void add(){
System.out.println("user ... add ...");
}
}
2.创建一个增强类
@Component
@Aspect //这个注解会创建一个代理对象
public class UserAdvice {
//前置通知 在被增强的方法之前执行,环绕之前之后执行
@Before("execution(* com.wk.spring5.aspectj.User.add(..))")
public void before(){
System.out.println("before");
}
//后置通知 在被增强的方法之后执行,环绕之后之后执行
@After("execution(* com.wk.spring5.aspectj.User.add(..))")
public void after(){
System.out.println("after");
}
//返回通知 在被增强的方法将返回值返回后执行
@AfterReturning("execution(* com.wk.spring5.aspectj.User.add(..))")
public void afterReturning(){
System.out.println("afterReturning");
}
//异常通知 在被增强的方法发生异常后执行
@AfterThrowing("execution(* com.wk.spring5.aspectj.User.add(..))")
public void afterThrowing(){
System.out.println("afterThrowing");
}
//环绕通知,可以在方法之前执行,也可以在方法之后执行
@Around("execution(* com.wk.spring5.aspectj.User.add(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("around之前");
proceedingJoinPoint.proceed(); //执行被增强的方法
System.out.println("around之后");
}
}
3.在配置文件中扫描创建对象
4.在配置文件中扫描创建代理对象
5.编写测试类
public class AspectjTest {
@Test
public void testAspectJ(){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("aspectj.xml");
User user = applicationContext.getBean("user", User.class);
user.add();
}
}
输出结果:
相同的切入点表达式也可以进行公共抽取,例如如上的"execution(* com.wk.spring5.aspectj.User.add(…))"都是相同的。可以通过Pointcut注解抽取。其效果是一样的。
@Pointcut("execution(* com.wk.spring5.aspectj.User.add(..))")
public void pointcut(){
}
//前置通知 在被增强的方法之前执行
@Before(value = "pointcut()")
public void before(){
System.out.println("before");
}
如果有多个增强类怎么设置优先级?
使用@Order(数字类型的值),值越小,越先执行
@Component
@Aspect
@Order(value = 0)
public class UserAdvice2 {
@Before("execution(* com.wk.spring5.aspectj.User.add(..))")
public void before(){
System.out.println("UserAdvice2的before方法执行");
}
}
@Component
@Aspect
@Order(value = 1)
public class UserAdvice {
/**
* 相同的切入点可以进行抽取
*/
@Pointcut("execution(* com.wk.spring5.aspectj.User.add(..))")
public void pointcut(){
}
//前置通知 在被增强的方法之前执行
@Before(value = "pointcut()")
public void before(){
System.out.println("before");
}
@After("execution(* com.wk.spring5.aspectj.User.add(..))")
public void after(){
System.out.println("after");
}
@AfterReturning("execution(* com.wk.spring5.aspectj.User.add(..))")
public void afterReturning(){
System.out.println("afterReturning");
}
@AfterThrowing("execution(* com.wk.spring5.aspectj.User.add(..))")
public void afterThrowing(){
System.out.println("afterThrowing");
}
@Around("execution(* com.wk.spring5.aspectj.User.add(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("around之前");
proceedingJoinPoint.proceed(); //执行被增强的方法
System.out.println("around之后");
}
}
现在有两个增强类同时增强User中的add方法。但因为设置了优先级
所以UserAdvice2中的方法先执行。
二、 基于xml的通知
1.创建一个类
public class Order {
public void order(String num){
System.out.println("orderNum : " + num);
}
}
2.创建增强的类
public class OrderAdvice {
public void before(JoinPoint point){
System.out.println("before 方法参数:" + point.getArgs()[0]);
}
public void after(JoinPoint point){
System.out.println("after");
}
public void around(ProceedingJoinPoint point) throws Throwable{
System.out.println("环绕之前执行");
point.proceed();
System.out.println("环绕之后执行");
}
public void afterReturn( ){
System.out.println("afterReturn");
}
public void exception(){
System.out.println("exception");
}
}
3.在配置文件中创建这两个类的对象
4.在配置文件中配置切入点表达式以及切面
<!--配置aop的增强-->
<aop:config>
<!--配置切入点(指明要对哪些类的哪些方法进行增强)-->
<aop:pointcut id="myPointCut" expression="execution(* com.wk.spring5.aspectj_xml.Order.order(..))"/>
<!--配置切面 ref:指向被增强的类 order:如果有多个增强类可以指定顺序-->
<aop:aspect ref="orderAdvice" order="0">
<!--用orderAdvice的before方法来做前置通知-->
<aop:before method="before" pointcut-ref="myPointCut"></aop:before>
<!--用orderAdvice的after方法来做后置通知-->
<aop:after method="after" pointcut-ref="myPointCut"></aop:after>
<!--用orderAdvice的afterReturn方法来做返回通知-->
<aop:after-returning method="afterReturn" pointcut-ref="myPointCut"></aop:after-returning>
<!--用orderAdvice的around方法来做环绕通知-->
<aop:around method="around" pointcut-ref="myPointCut"></aop:around>
<!--用orderAdvice的exception方法来做异常通知-->
<aop:after-throwing method="exception" pointcut-ref="myPointCut"></aop:after-throwing>
</aop:aspect>
</aop:config>
5.编写测试类
@Test
public void testAspectJ_XML(){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("aspectj_xml.xml");
Order order = applicationContext.getBean("order", Order.class);
order.order(UUID.randomUUID().toString());
}
输出结果:
可以看到用xml方式同样可以完成方法增强。
如果改用纯注解方法需要单独建一个配置类。其中EnableAspectJAutoProxy注解可以创建代理对象,如果不开启这个,则无法进行增强。
@Configuration
@ComponentScan(basePackages = "com.wk.spring5.componentscan")
@EnableAspectJAutoProxy
public class SpringConfig {
}