一、代理模式
常用的代理模式有,jdk動態代理s和CGLIB動態代理模式,JDK動態代理是java.lang.reflect.*包提供的方式,它必須提供一個接口才能產生代理對象。
下面講解jdk動態代理,如下圖:
假設有這樣一個場景,你的公司是一個軟件公司,你是一位軟件工程師,客戶帶着需求過來,顯然不會先去直接找你,而是去找一個叫商務對象的人,此時商務就是代理你的人,同時也是與客戶交談的人。
下面看一個案例:
第一步,先定義一個接口:
package com.hand.proxy;
public interface HelloWorld {
public void sayHelloWorld();
public void sayHai();
}
第二步,實現該接口:
package com.hand.proxy;
public class HelloWorldImpl implements HelloWorld {
public void sayHelloWorld() {
System.out.println("hello world!");
}
public void sayHai() {
System.out.println("您好,我要代理!");
}
}
第三步,創建代理類,實現InvocationHandler接口,實現invoke方法,參數解析如下:
package com.hand.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JDKExampleProxy implements InvocationHandler{
private Object target=null;
/**
* 生成代理對象的方法
*/
public Object bind(Object target) {
this.target=target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this);
}
/**
* proxt爲代理對象,就是bind方法生成的對象
* method爲當前調度的方法
* args爲調度方法的參數
*/
public Object invoke(Object proxy,
Method method,
Object[] args) throws Throwable {
System.out.println("進入代理方法!");
System.out.println("在調度真實方法之前的服務!");
//在調度真實方法前可以通過此方法執行其他的方法邏輯,此處甚至可以不調用helloWorld打印
Object obj=method.invoke(target, args);
//返回執行的結果
return obj;
}
}
驗證:
package com.hand.proxy;
public class test01 {
public static void main(String[]args) {
JDKExampleProxy jdk=new JDKExampleProxy();
//創建代理對象
HelloWorld proxy=(HelloWorld) jdk.bind(new HelloWorldImpl());
proxy.sayHelloWorld();
proxy.sayHai();
}
}
打印結果:
進入代理方法!
在調度真實方法之前的服務!
hello world!
進入代理方法!
在調度真實方法之前的服務!
您好,我要代理!
由此可以發現,在執行真實的方法前後,我們還可以添加其他邏輯,jdk動態代理必須實現java.lang.reflect.InvocationHandler類,由此商務控制了客戶對軟件工程師的訪問!代理模式可以增加了對實際訪問對象的擴展。
CGLIB代理與JDK動態代理模式的區別:jdk需要實現接口,而CGLIB代理模式不需要實現接口來實現代理。
二、JDK動態代理的應用
mybatis的Mapper接口的工作原理就是JDK動態代理,Mybatis運行時會使用JDK動態代理爲Mapper接口生成代理對象proxy,代理對象會攔截接口方法,轉而執行mapperStatement所代表的sql,然後將sql執行結果返回。
三、面試
1. 什麼是jdk動態代理?
jdk動態代理是基於java反射技術實現的一種通過實現目標接口來創建代理對象的一種代理方式。