在Spring中使用AOP进行切面编程主要有以下几种方式:
- XML配置
- XML+注解
- 纯注解
XML配置
新建实体类XmlAopBean及切片类XmlAopService
实体类XmlAopBean
package XmlAopBean;
import java.text.MessageFormat;
public class XmlAopBean {
public void runWithoutArgs() {
System.out.println("这是无参方法。");
}
public void runWithArgs(Integer arg) {
Integer i=1/arg;
System.out.println(MessageFormat.format("这是有参方法,参数:{0}", arg));
}
}
AOP类XmlAopService
package XmlAopBean;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import java.text.MessageFormat;
public class XmlAopService {
public void doBefore(JoinPoint joinPoint) {
System.out.println(MessageFormat.format("前置通知参数:{0}", joinPoint.getArgs()));
}
public void doAfter(JoinPoint joinPoint) {
System.out.println(MessageFormat.format("后置通知方法:{0}", joinPoint.getSignature()));
}
public void doEnd(JoinPoint joinPoint) {
System.out.println(MessageFormat.format("最终通知目标类:{0}", joinPoint.getTarget()));
}
public void doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println(MessageFormat.format("前环绕通知代码位置:{0}", proceedingJoinPoint.getSourceLocation()));
proceedingJoinPoint.proceed();
System.out.println(MessageFormat.format("后环绕通知执行类型:{0}", proceedingJoinPoint.getKind()));
}
public void doAfterThrow(JoinPoint joinPoint){
System.out.println(MessageFormat.format("异常通知{0}", joinPoint.getThis()));
}
}
JoinPoint :获取切入点方法的相关信息
ProceedingJoinPoint :环绕通知内切入点方法占位
xmlAopBean.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns="http://www.springframework.org/schema/beans"
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-4.0.xsd"
>
<bean class="XmlAopBean.XmlAopBean" id="xmlAopBean"/>
<bean class="XmlAopBean.XmlAopService" id="xmlAopService"/>
<aop:config>
<aop:pointcut id="xmlAopPointCut" expression="execution(void XmlAopBean.XmlAopBean.*(..))"/>
<aop:aspect ref="xmlAopService">
<aop:before method="doBefore" pointcut-ref="xmlAopPointCut"/>
<aop:after method="doAfter" pointcut-ref="xmlAopPointCut"/>
<aop:after-returning method="doEnd" pointcut-ref="xmlAopPointCut"/>
<aop:around method="doAround" pointcut-ref="xmlAopPointCut"/>
</aop:aspect>
</aop:config>
</beans>
导入依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.14</version>
</dependency>
引入约束
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="...
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd"
配置AOP
<aop:config>
<aop:pointcut id="xmlAopPointCut" expression="execution(void XmlAopBean.XmlAopBean.*(..))"/>
<aop:aspect ref="xmlAopService">
<aop:before method="doBefore" pointcut-ref="xmlAopPointCut"/>
<aop:after method="doAfter" pointcut-ref="xmlAopPointCut"/>
<aop:after-returning method="doEnd" pointcut-ref="xmlAopPointCut"/>
<aop:around method="doAround" pointcut-ref="xmlAopPointCut"/>
</aop:aspect>
</aop:config>
单元测试
import AnnotationAopBean.AnnotationAopBean;
import XmlAopBean.XmlAopBean;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {BaseConfig.class})
public class AOPBeanTest {
...
@Test
public void xmlAopBeanTest() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("xmlAopBean.xml");
XmlAopBean xmlAopBean = applicationContext.getBean("xmlAopBean", XmlAopBean.class);
xmlAopBean.runWithArgs(1);
xmlAopBean.runWithoutArgs();
}
}
输出结果
前置通知参数:1
前环绕通知代码位置:org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint$SourceLocationImpl@6d5620ce
这是有参方法,参数:1
后环绕通知执行类型:method-execution
最终通知目标类:XmlAopBean.XmlAopBean@60db1c0e
后置通知方法:void XmlAopBean.XmlAopBean.runWithArgs(Integer)
前置通知参数:{0}
前环绕通知代码位置:org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint$SourceLocationImpl@18f8cd79
这是无参方法。
后环绕通知执行类型:method-execution
最终通知目标类:XmlAopBean.XmlAopBean@60db1c0e
后置通知方法:void XmlAopBean.XmlAopBean.runWithoutArgs()
XML+注解
新建实体类XmlAnnotationAopBean和AOP类XmlAnnotationAopService
实体类XmlAnnotationAopBean
package XmlAnnotationAopBean;
import org.springframework.stereotype.Component;
import java.text.MessageFormat;
@Component
public class XmlAnnotationAopBean {
public void runWithoutArgs() {
System.out.println("这是无参方法。");
}
public void runWithArgs(Integer arg) {
Integer i = 1 / arg;
System.out.println(MessageFormat.format("这是有参方法,参数:{0}", arg));
}
}
AOP类XmlAnnotationAopService
package XmlAnnotationAopBean;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import java.text.MessageFormat;
@Component
@Aspect
public class XmlAnnotationAopService {
@Pointcut("execution(void XmlAnnotationAopBean.*(..))")
public void pointCut() {
}
@Before("pointCut()")
public void doBefore(JoinPoint joinPoint) {
System.out.println(MessageFormat.format("前置通知参数:{0}", joinPoint.getArgs()));
}
@After("pointCut()")
public void doAfter(JoinPoint joinPoint) {
System.out.println(MessageFormat.format("后置通知方法:{0}", joinPoint.getSignature()));
}
@AfterReturning("pointCut()")
public void doEnd(JoinPoint joinPoint) {
System.out.println(MessageFormat.format("最终通知目标类:{0}", joinPoint.getTarget()));
}
@Around("pointCut()")
public void doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println(MessageFormat.format("前环绕通知代码位置:{0}", proceedingJoinPoint.getSourceLocation()));
proceedingJoinPoint.proceed();
System.out.println(MessageFormat.format("后环绕通知执行类型:{0}", proceedingJoinPoint.getKind()));
}
@AfterThrowing("pointCut()")
public void doAfterThrow(JoinPoint joinPoint){
System.out.println(MessageFormat.format("异常通知{0}", joinPoint.getThis()));
}
}
@Aspect:指定为切面类
XmlAnnotationAopBean.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
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-4.0.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"
>
<context:component-scan base-package="XmlAnnotationAopBean"/>
<aop:aspectj-autoproxy/>
</beans>
aop:aspectj-autoproxy/:开启自动AOP代理
单元测试
import XmlAnnotationAopBean.XmlAnnotationAopBean;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:XmlAnnotationAopBean.xml")
public class XmlAnnotationAopBeanTest {
@Autowired
private XmlAnnotationAopBean xmlAnnotationAopBean;
@Test
public void xmlAnnotationAopBeanTest() {
xmlAnnotationAopBean.runWithArgs(1);
xmlAnnotationAopBean.runWithoutArgs();
}
}
输出结果
前环绕通知代码位置:org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint$SourceLocationImpl@5965d37
前置通知参数:1
这是有参方法,参数:1
后环绕通知执行类型:method-execution
后置通知方法:void XmlAnnotationAopBean.XmlAnnotationAopBean.runWithArgs(Integer)
最终通知目标类:XmlAnnotationAopBean.XmlAnnotationAopBean@38467116
前环绕通知代码位置:org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint$SourceLocationImpl@5b7a7f33
前置通知参数:{0}
这是无参方法。
后环绕通知执行类型:method-execution
后置通知方法:void XmlAnnotationAopBean.XmlAnnotationAopBean.runWithoutArgs()
最终通知目标类:XmlAnnotationAopBean.XmlAnnotationAopBean@38467116
纯注解
新建配置注解类BaseConfig、实体类AnnotationAopBean和AOP类AnnotationAopService
注解配置BaseConfig
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@ComponentScan(basePackages = "AnnotationAopBean")
@EnableAspectJAutoProxy
public class BaseConfig {
}
@EnableAspectJAutoProxy:开启自动AOP代理
实体类AnnotationAopBean
package AnnotationAopBean;
import org.springframework.stereotype.Component;
import java.text.MessageFormat;
@Component
public class AnnotationAopBean {
public void runWithoutArgs() {
System.out.println("这是无参方法。");
}
public void runWithArgs(Integer arg) {
Integer i = 1 / arg;
System.out.println(MessageFormat.format("这是有参方法,参数:{0}", arg));
}
}
AOP类AnnotationAopService
package AnnotationAopBean;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import java.text.MessageFormat;
@Component
@Aspect
public class AnnotationAopService {
@Pointcut("execution(void AnnotationAopBean.*(..))")
public void pointCut() {
}
@Before("pointCut()")
public void doBefore(JoinPoint joinPoint) {
System.out.println(MessageFormat.format("前置通知参数:{0}", joinPoint.getArgs()));
}
@After("pointCut()")
public void doAfter(JoinPoint joinPoint) {
System.out.println(MessageFormat.format("后置通知方法:{0}", joinPoint.getSignature()));
}
@AfterReturning("pointCut()")
public void doEnd(JoinPoint joinPoint) {
System.out.println(MessageFormat.format("最终通知目标类:{0}", joinPoint.getTarget()));
}
@Around("pointCut()")
public void doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println(MessageFormat.format("前环绕通知代码位置:{0}", proceedingJoinPoint.getSourceLocation()));
proceedingJoinPoint.proceed();
System.out.println(MessageFormat.format("后环绕通知执行类型:{0}", proceedingJoinPoint.getKind()));
}
@AfterThrowing("pointCut()")
public void doAfterThrow(JoinPoint joinPoint){
System.out.println(MessageFormat.format("异常通知{0}", joinPoint.getThis()));
}
}
单元测试
import AnnotationAopBean.AnnotationAopBean;
import XmlAopBean.XmlAopBean;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {BaseConfig.class})
public class AOPBeanTest {
@Autowired
private AnnotationAopBean annotationAopBean;
@Test
public void annotationAopBeanTest() {
annotationAopBean.runWithArgs(1);
annotationAopBean.runWithoutArgs();
}
....
}
输出结果
前环绕通知代码位置:org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint$SourceLocationImpl@5f9edf14
前置通知参数:1
这是有参方法,参数:1
后环绕通知执行类型:method-execution
后置通知方法:void AnnotationAopBean.AnnotationAopBean.runWithArgs(Integer)
最终通知目标类:AnnotationAopBean.AnnotationAopBean@68746f22
前环绕通知代码位置:org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint$SourceLocationImpl@2f01783a
前置通知参数:{0}
这是无参方法。
后环绕通知执行类型:method-execution
后置通知方法:void AnnotationAopBean.AnnotationAopBean.runWithoutArgs()
最终通知目标类:AnnotationAopBean.AnnotationAopBean@68746f22
源码下载
git@github.com:Angryshark128/Practice.git