Spring AOP Aspectj实现

Spring AOP 已经集成了 AspectJ,使用AspectJ实现时,不需要让自定义的通知类实现特定接口,需要在配置<aop:config>标签的时候使用<aop:aspect>标签配置切面,引用通知提供类。

我们先自定义一个定义了所需的通知方法的通知提供类。

package com.test.advice;

import org.aspectj.lang.ProceedingJoinPoint;

public class MyAdvice {
	
	public void myBeforeAdvice() {
		System.out.println("aspect before advice");
	}
	
	public void myAfterAdvice() {
		System.out.println("aspect after advice");
	}
	
	public void myAfterReturningAdvice() {
		System.out.println("aspect after returning advice");
	}
	
	public void myThrowsAdvice() {
		System.out.println("aspect throws advice");
	}
	
	public void myArroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
		System.out.println("aspect arround advice - before");
		proceedingJoinPoint.proceed();
		System.out.println("aspect arround advice - after");
	}
}

需要注意的是,在环绕通知方法中,需要一个ProceedingJoinPoint类型的形参,在执行完环绕前置通知之后执行proceedingJoinPoint.proceed()方法让目标方法执行,然后才会执行环绕后置通知。简单理解,环绕通知=前置+目标方法执行+后置通知,proceed方法就是用于启动目标方法执行的。

然后再配置applicationContext.xml。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

	<bean id="demo" class="com.test.Demo"></bean>
	<bean id="myAdvice" class="com.test.advice.MyAdvice"></bean>

	<aop:config>
		<aop:aspect ref="myAdvice">
			<aop:pointcut expression="execution(* com.test.Demo.function2())"
				id="mypointcut1" />
			<aop:before method="myBeforeAdvice" pointcut-ref="mypointcut1"/>
			<aop:after method="myAfterAdvice" pointcut-ref="mypointcut1"/>
			<aop:after-returning method="myAfterReturningAdvice" pointcut-ref="mypointcut1"/>
			<aop:after-throwing method="myThrowsAdvice" pointcut-ref="mypointcut1"/>
			<aop:around method="myArroundAdvice" pointcut-ref="mypointcut1"/>
		</aop:aspect>
	</aop:config>

</beans> 

被代理的Demo类如下。

package com.test;

public class Demo {

	public void function1() {
		System.out.println("Demo function1");
	}
	
	public void function2() {
		System.out.println("Demo function2");
	}
	
	public void function3() {
		System.out.println("Demo function3");
	}

}

测试类。

package com.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		@SuppressWarnings("resource")
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
		
		Demo demo = ac.getBean("demo",Demo.class);
		demo.function1();
		demo.function2();
		demo.function3();
	}

}

执行结果如下:

在这里插入图片描述

需要注意的是,通知方法的执行顺序与<aop:aspec>中配置的顺序有关。

使用注解实现

我们可以使用注解的方式替换掉在applicationContext.xml中配置<aop:config>标签。

在通知方法提供类上使用@Aspect注解声明,通知方法使用各自的注解,并配置切点的路径。

package com.test.advice;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class MyAdvice {
	
	@Before("com.test.Demo.function2()")
	public void myBeforeAdvice() {
		System.out.println("aspect before advice");
	}
	
	@After("com.test.Demo.function2()")
	public void myAfterAdvice() {
		System.out.println("aspect after advice");
	}
	
	@AfterReturning("com.test.Demo.function2()")
	public void myAfterReturningAdvice() {
		System.out.println("aspect after returning advice");
	}
	
	@AfterThrowing("com.test.Demo.function2()")
	public void myThrowsAdvice() {
		System.out.println("aspect throws advice");
	}
	
	@Around("com.test.Demo.function2()")
	public void myArroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
		System.out.println("aspect arround advice - before");
		proceedingJoinPoint.proceed();
		System.out.println("aspect arround advice - after");
	}
}

在切点处使用@Pointcut注解,配置切点表达式。

package com.test;

import org.aspectj.lang.annotation.Pointcut;

public class Demo {

	public void function1() {
		System.out.println("Demo function1");
	}
	
	@Pointcut("execution(* com.test.Demo.function2())")
	public void function2() {
		System.out.println("Demo function2");
	}
	
	public void function3() {
		System.out.println("Demo function3");
	}

}

在applicationContext.xml中配置相关的bean和标签<aop:aspectj-autoproxy/>开启aspectj注解支持。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

	<bean id="demo" class="com.test.Demo"></bean> 
	<bean id="myAdvice" class="com.test.advice.MyAdvice"></bean> 
 	<aop:aspectj-autoproxy/>

</beans> 

测试类中:

package com.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		@SuppressWarnings("resource")
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
		
		Demo demo = ac.getBean("demo",Demo.class);
		demo.function1();
		demo.function2();
		demo.function3();
	}

}

执行结果:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值