spring(三)--動態代理/AOP

一、靜態代理

可以用現實生活中的例子來說,房東有房子要出售,但是不可能一下子就找到客戶,此時可以交給代理去做,那麼代理就會和房東一樣具有租房的權利,但是代理就不一定只會去租房,還會收取中介費等,而客戶最後也可以通過代理實現租房。
放到程序中,可以認爲是代理實現的不僅僅是幫房東租房的業務,還可以實現其他的功能,這樣就可以擴充具體實現類的功能!!
在這裏插入圖片描述
通過上圖,可以得到四個角色:客戶、代理角色、真實角色、抽象接口
接口:租房

public interface Rent {
    public void rent();
}

房東 : 真實的角色

public class Host implements Rent{

    public void rent() {
        System.out.println("房東出租房子");
    }
}

代理角色:中介

//中介代理  幫房東租房
public class Agent implements Rent {
    //拿房東
    private Host host;
    public Agent(Host host){
        this.host=host;
    }


    public void rent() {
        look();
        host.rent();
        fee();
    }
    public void look(){
        System.out.println("帶客戶看房");
    }
    public void fee(){
        System.out.println("收取中介費");
    }
}

client:客戶

public class Client {
    public static void main(String[] args) {
        Agent agent = new Agent(new Host());
        agent.rent();
    }
}

二、動態代理

  • 動態代理和靜態代理角色一樣,動態代理是直接生成的,不是直接寫的。
    Spring AOP中的動態代理主要有兩種方式:JDK動態代理和CGLIB動態代理
    JDK動態代理通過反射來接收被代理的類,並且要求被代理的類必須實現一個接口。JDK動態代理的核心是InvocationHandler接口和Proxy類。現在都推薦面向接口編程,我們做的項目都是各種接口+實現類,所以是不是覺得這種代理方式和現在的接口編程很符合呢!
    下面我們延續上面的例子進行說明,上面的靜態代理對象是我們寫出來的,而動態代理可以生成!!
    在這裏插入圖片描述
    在這裏插入圖片描述
    在這裏插入圖片描述

完整代碼

房東 真實的角色

public class Host implements Rent{

    public void rent() {
        System.out.println("房東出租房子");
    }
}

Rent 接口

public interface Rent {
    public void rent();
}

自動生成代理類

package com.zhoudan.demo2;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

//可以自動生成代理類
public class ProxyInvocationHandler implements InvocationHandler {
    //被代理的接口
    private Rent rent;

    public void setRent(Rent rent) {
        this.rent = rent;
    }

    //生成得到代理類
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);
    }
    //處理代理實例 返回結果 可以理解爲得到調用方法
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
       seeHouse();
        Object result = method.invoke(rent, args);
        fee();
        return result;
    }
    public void seeHouse(){
        System.out.println("中介帶着看房子");
    }
    public void fee(){
        System.out.println("中介收取中介費");
    }
}

client

public class Client {
    public static void main(String[] args) {
        //真實角色
        Host host = new Host();
        //代理角色沒有
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        //處理接口對象
        pih.setRent(host);
        Rent proxy = (Rent) pih.getProxy();
        proxy.rent();

    }
}

三、AOP

與AspectJ的靜態代理不同,Spring AOP使用的動態代理,所謂的動態代理就是說AOP框架不會去修改字節碼,而是在內存中臨時爲方法生成一個AOP對象(我們可以把它稱之爲‘代理對象’),這個AOP對象包含了目標對象的全部方法,並且在特定的切點做了增強處理,並回調原對象的方法。

  • 橫切關注點:跨越應用程序多個模塊的方法或功能。即是,與我們業務邏輯無關的,但是我們需要關注的部分,就是橫切關注點。如日誌 , 安全 , 緩存 , 事務等等 …

  • 切面(ASPECT):橫切關注點 被模塊化 的特殊對象。即,它是一個類。

  • 通知(Advice):切面必須要完成的工作。即,它是類中的一個方法。

  • 目標(Target):被通知對象。

  • 代理(Proxy):向目標對象應用通知之後創建的對象。

  • 切入點(PointCut):切面通知 執行的 “地點”的定義。

  • 連接點(JointPoint):與切入點匹配的執行點。

使用aop時要先導入依賴和在xml中進行相應的配置和約束:

 <dependencies>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.4</version>
        </dependency>
    </dependencies>

在這裏插入圖片描述
定義一個接口和一個實現類:
在這裏插入圖片描述
有以下三種實現方式:
方式一:
先定義兩個類,分別執行前置通知和後置通知
在這裏插入圖片描述
在這裏插入圖片描述
方式二:使用自定義的類作爲切入面
在這裏插入圖片描述
方式三:使用註解
在這裏插入圖片描述
由於筆者能力有限,對aop的理解還不夠透徹。如果有錯誤的地方,大家可以多多指出,我們共同進步!!

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