AOP概念
AOP的實作
方式1:使用Spring的API接口
1:編寫一個類,實作相關的接口
2:核心配置檔案
3:單元測試
方式2:自定義實作AOP
1:自定義一個類
2:核心配置檔案
3:單元測試
方式3:使用注解實作
1:開啟AOP注解支援
2:自定義切面類使用注解
3:單元測試
4:各種切面注解測試
AOP概念
百度百科:
在軟體業,AOP為Aspect Oriented Programming的縮寫,意為:面向切面程式設計,通過預編譯方式和運作期間動态代理實作程式功能的統一維護的一種技術。AOP是OOP的延續,是軟體開發中的一個熱點,也是Spring架構中的一個重要内容,是函數式程式設計的一種衍生範型。利用AOP可以對業務邏輯的各個部分進行隔離,進而使得業務邏輯各部分之間的耦合度降低,提高程式的可重用性,同時提高了開發的效率。
舉個栗
![]()
Spring之AOP原理及多種實作方式 ![]()
Spring之AOP原理及多種實作方式 ![]()
Spring之AOP原理及多種實作方式 AOP的實作
要使用Spring的AOP織入,就得使用相關的包,這裡使用Maven導入
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
我們舉例的業務service層和實作類
package com.lingaolu.service;
/**
* @author 林高祿
* @create 2020-11-10-10:43
*/
public interface StudentService {
void mathod1();
String mathod2();
}
package com.lingaolu.impl;
import com.lingaolu.service.StudentService;
/**
* @author 林高祿
* @create 2020-11-10-10:46
*/
public class StudentServiceImpl implements StudentService {
@Override
public void mathod1() {
System.out.println("通路mathod1");
}
@Override
public String mathod2() {
System.out.println("通路mathod2");
return "方法2傳回值";
}
}
方式1:使用Spring的API接口
1:編寫一個類,實作相關的接口
![]()
Spring之AOP原理及多種實作方式
package com.lingaolu.system;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
/**
* @author 林高祿
* @create 2020-11-10-10:54
*/
public class MyLog implements MethodBeforeAdvice,AfterReturningAdvice {
@Override
public void before(Method method, Object[] objects, Object target) throws Throwable {
System.out.println(target.getClass().getName()+"的"+method.getName()+"執行前aa......");
}
@Override
public void afterReturning(Object returnVar, Method method, Object[] objects, Object target) throws Throwable {
System.out.println(target.getClass().getName()+"的"+method.getName()+"執行後......,傳回值:"+returnVar);
}
}
2:核心配置檔案
![]()
Spring之AOP原理及多種實作方式
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--注冊bean-->
<bean id="studentService" class="com.lingaolu.impl.StudentServiceImpl"/>
<bean id="myLog" class="com.lingaolu.system.MyLog"/>
<!--配置AOP,需要導入AOP限制-->
<aop:config>
<!--切入點,expression表達式:execution(* * * * *)-->
<!-- 5個*的位置分别表示,傳回值,包,類,方法參數,更多的可以去查資料 -->
<!-- 我們這裡的配置,表示這個類的所有方法,..表示任意參數類型 -->
<aop:pointcut id="pointcut" expression="execution(* com.lingaolu.impl.StudentServiceImpl.*(..))"/>
<!-- 為切入點執行增加 -->
<aop:advisor advice-ref="myLog" pointcut-ref="pointcut"/>
</aop:config>
</beans>
3:單元測試
![]()
Spring之AOP原理及多種實作方式 方式2:自定義實作AOP
1:自定義一個類
![]()
Spring之AOP原理及多種實作方式
package com.lingaolu.system;
/**
* @author 林高祿
* @create 2020-11-10-10:54
*/
public class MyLog {
public void myBefore(){
System.out.println("調用方法前......");
}
public String myAfter(){
System.out.println("調用方法後......");
return "調用方法後傳回值";
}
}
2:核心配置檔案
![]()
Spring之AOP原理及多種實作方式
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--注冊bean-->
<bean id="studentService" class="com.lingaolu.impl.StudentServiceImpl"/>
<bean id="myLog" class="com.lingaolu.system.MyLog"/>
<!--配置AOP,需要導入AOP限制-->
<aop:config>
<!--切入點,expression表達式:execution(* * * * *)-->
<!-- 5個*的位置分别表示,傳回值,包,類,方法參數,更多的可以去查資料 -->
<!-- 我們這裡的配置,表示這個類的所有方法,..表示任意參數類型 -->
<aop:pointcut id="pointcut" expression="execution(* com.lingaolu.impl.StudentServiceImpl.*(..))"/>
<!-- 配置切面類 -->
<aop:aspect ref="myLog">
<!-- 切面調用方法前,調用切面類的myBefor方法,所作用于的切面pointcut -->
<aop:before method="myBefore" pointcut-ref="pointcut"/>
<!-- 切面調用方法後,調用切面類的myAfter方法,所作用于的切面pointcut -->
<aop:after method="myAfter" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
</beans>
3:單元測試
![]()
Spring之AOP原理及多種實作方式 方式3:使用注解實作
1:開啟AOP注解支援
![]()
Spring之AOP原理及多種實作方式
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--注冊bean-->
<bean id="studentService" class="com.lingaolu.impl.StudentServiceImpl"/>
<bean id="myLog" class="com.lingaolu.system.MyLog"/>
<!--開啟AOP注解支援,proxy-target-class預設為false,表示JDK方式實作動态代理,true表示cglib方式-->
<aop:aspectj-autoproxy proxy-target-class="false"/>
</beans>
2:自定義切面類使用注解
![]()
Spring之AOP原理及多種實作方式
package com.lingaolu.system;
import org.aspectj.lang.annotation.*;
/**
* @author 林高祿
* @create 2020-11-10-10:54
*/
@Aspect
public class MyLog {
@Before("execution(* com.lingaolu.impl.StudentServiceImpl.*(..))")
public void myBefore(){
System.out.println("調用方法前......");
}
@After("execution(* com.lingaolu.impl.StudentServiceImpl.*(..))")
public String myAfter(){
System.out.println("調用方法後......");
return "調用方法後傳回值";
}
}
3:單元測試
![]()
Spring之AOP原理及多種實作方式 4:各種切面注解測試
![]()
Spring之AOP原理及多種實作方式
package com.lingaolu.system;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
/**
* @author 林高祿
* @create 2020-11-10-10:54
*/
@Aspect
public class MyLog {
@Before("execution(* com.lingaolu.impl.StudentServiceImpl.*(..))")
public void myBefore(){
System.out.println("調用方法前......");
}
@After("execution(* com.lingaolu.impl.StudentServiceImpl.*(..))")
public String myAfter(){
System.out.println("調用方法後......");
return "調用方法後傳回值";
}
/**
* 在環繞增強中,我們可以給定一個參數,代表我們要擷取處理切入的點
* @param pj 擷取處理切入的點
*/
@Around("execution(* com.lingaolu.impl.StudentServiceImpl.*(..))")
public void Around(ProceedingJoinPoint pj) throws Throwable {
System.out.println("調用方法環繞......");
// 擷取簽名
Signature signature = pj.getSignature();
System.out.println(signature);
// 方法執行
Object proceed = pj.proceed();
System.out.println(proceed);
}
}
測試結果符合![]()
Spring之AOP原理及多種實作方式