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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章