spring的AOP知識點2.0
一 AOP 相關概念
Joinpoint(連線點):所謂連線點是指那些被攔截到的點。在spring中,這些點指的是方法,因為spring只支援方法型別的連線點.
Pointcut(切入點):所謂切入點是指我們要對哪些Joinpoint進行攔截的定義.
Advice(通知/增強):所謂通知是指攔截到Joinpoint之後所要做的事情就是通知.通知分為前置通知,後置通知,異常通知,最終通知,環繞通知(切面要完成的功能)
Introduction(引介):引介是一種特殊的通知在不修改類程式碼的前提下, Introduction可以在執行期為類動態地新增一些方法或Field.
Target(目標物件):代理的目標物件
Weaving(織入):是指把增強應用到目標物件來建立新的代理物件的過程.
spring採用動態代理織入,而AspectJ採用編譯期織入和類裝在期織入
Proxy(代理):一個類被AOP織入增強後,就產生一個結果代理類
Aspect(切面): 是切入點和通知(引介)的結合
二、 AOP 的底層實現
AOP 底層使用的代理技術 : JDK動態代理 和 CGlib的動態代理。
AOP 開發規範 : AOP聯盟為通知Advice定義了org.aopalliance.aop.Interface.Advice。 Spring AOP 實現 AOP聯盟定義 規範
傳統Spring AOP 提供 五類 Advice
a 前置通知(程式碼增強) org.springframework.aop.MethodBeforeAdvice 在目標方法執行前實施增強
b 後置通知 org.springframework.aop.AfterReturningAdvice 在目標方法執行後實施增強
c 環繞通知org.aopalliance.intercept.MethodInterceptor 在目標方法執行前後實施增強
d 異常丟擲通知 org.springframework.aop.ThrowsAdvice 在方法丟擲異常後實施增強
e 引介通知 org.springframework.aop.IntroductionInterceptor 在目標類中新增一些新的方法和屬性
2、 Spring 的切面 Advisor
Advisor 就是對PointCut 應用 Advice (通常所說Advisor 指只有一個Point 和 一個 Advice )
通過配置實現增強
採用jdk動態代理實現,有一個介面UserService,實現類 UserImpl, 不配置切點
UserService介面
package dflx; public interface UserService { public void add(); public void serach(); }
實現類 UserImpl
public class UserImpl implements UserService { @Override public void add() { System.out.println(" add user"); } @Override public void serach() { System.out.println("search user"); } }
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" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 不帶切點和切面 --> <!-- 被代理物件 --> <bean id="user" class="dflx.UserImpl"></bean> <!-- 增強 --> <bean id="mybeforeadvice" class="dflx.MethodBeforeTest"></bean> <bean id="userDAOProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <!-- 目標 --> <property name="target" ref="user"></property> <!-- 針對介面代理 --> <property name="proxyInterfaces" value="dflx.UserService"></property> <property name="interceptorNames" value="mybeforeadvice"></property> </bean> </beans>

image.png
通過如下方法測試
@Test public void test() { ApplicationContext app=new ClassPathXmlApplicationContext("app.xml"); UserService user=(UserService) app.getBean("userDAOProxy"); user.add(); user.serach(); }
結果如下
前置增強----------- add user 前置增強----------- search user

image.png
採用Cglib的動態代理,有切點和切面。
有一個 OrderDAO類,Advice通知增強類MyMethodInterceptor
public class OrderDAO { public void add() { System.out.println(" 新增訂單"); } public void delete() { System.out.println(" 刪除訂單"); } public void search() { System.out.println(" 查詢訂單"); } }
Advice通知增強類
import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; public class MyMethodInterceptor implements MethodInterceptor { @Override public Object invoke(MethodInvocation arg) throws Throwable { System.out.println("環繞前增強"); Object resultObject=arg.proceed(); //目標方法執行 System.out.println("環繞後增強"); return resultObject; } }
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" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 帶有切點的切面 --> <!-- 被代理的物件 --> <bean id="orderDAO" class="day0916.OrderDAO"></bean> <!-- 增強 --> <bean id="mymethodinter" class="day0916.MyMethodInterceptor"></bean> <!-- 定義切點切面 --> <bean id="myadvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <property name="pattern" value=".*"></property> <property name="advice" ref="mymethodinter"></property> </bean> <!-- 建立代理 --> <bean id="orderDAOProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <!-- 目標 --> <property name="target" ref="orderDAO"></property> <!-- 針對類代理 --> <property name="proxyTargetClass" value="true"></property> <!-- 增強 --> <property name="interceptorNames" value="myadvisor"></property> </bean> </beans>
測試類如下
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:app2.xml") public class SpringTest { @Autowired @Qualifier("orderDAOProxy") private OrderDAO orderDAO; @Test public void test() { orderDAO.add(); orderDAO.search(); orderDAO.delete(); } }
結果如下
環繞前增強 新增訂單 環繞後增強 環繞前增強 查詢訂單 環繞後增強 環繞前增強 刪除訂單 環繞後增強

image.png