在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
源碼下載
[email protected]:Angryshark128/Practice.git