爲啥要用代理??
代理能夠對原有邏輯進行加強,好比咱們去租房,能夠去找中介(也就是代理),而不是咱們本身找。
代理主要就是對原有方法進行加強的。
代理分爲靜態代理和動態代理。java
package designpattern.proxy.staticproxy; /** * 接口:租房 */ public interface IRentingHouse { void rentHosue(); }
package designpattern.proxy.staticproxy; import designpattern.proxy.staticproxy.IRentingHouse; public class RentingHouseImpl implements IRentingHouse { @Override public void rentHosue() { System.out.println("我要租用一室一廳的房子"); } }
package designpattern.proxy.staticproxy; import designpattern.proxy.staticproxy.IRentingHouse; public class RentingHouseProxy implements IRentingHouse { private IRentingHouse rentingHouse; public RentingHouseProxy(IRentingHouse rentingHouse) { this.rentingHouse = rentingHouse; } @Override public void rentHosue() { System.out.println("中介(代理)收取服務費3000元"); rentingHouse.rentHosue(); System.out.println("客戶信息賣了3毛錢"); } }
package designpattern.proxy.staticproxy; import designpattern.proxy.staticproxy.IRentingHouse; import designpattern.proxy.staticproxy.RentingHouseImpl; import designpattern.proxy.staticproxy.RentingHouseProxy; public class Test { public static void main(String[] args) { IRentingHouse rentingHouse = new RentingHouseImpl(); // 本身要租用一個一室一廳的房子 // rentingHouse.rentHosue(); RentingHouseProxy rentingHouseProxy = new RentingHouseProxy(rentingHouse); rentingHouseProxy.rentHosue(); } }
靜態代理和動態代理的區別主要是動態代理看不到代理類,由底層經過反射實現
分爲jdk動態代理和Cglib動態代理
jdk動態代理所代理的對象必須實現接口(由於要傳入),而Cglib代理不須要。ide
package designpattern.proxy.dynamicproxy; /** * 接口:租房 * jdk動態代理/cglib動態代理 */ public interface IRentingHouse { void rentHosue(); }
package designpattern.proxy.dynamicproxy; import designpattern.proxy.dynamicproxy.IRentingHouse; /** * 委託方(委託對象) */ public class RentingHouseImpl implements IRentingHouse { @Override public void rentHosue() { System.out.println("我要租用一室一廳的房子"); } }
package designpattern.proxy.dynamicproxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * @author 應癲 */ public class JdkProxy { public static void main(String[] args) { IRentingHouse rentingHouse = new RentingHouseImpl(); // 委託對象---委託方 // 從代理對象工廠獲取代理對象 IRentingHouse jdkProxy = (IRentingHouse) ProxyFactory.getInstance().getJdkProxy(rentingHouse); jdkProxy.rentHosue(); } }
package designpattern.proxy.dynamicproxy; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * @author 應癲 * * * 代理對象工廠:生成代理對象的 */ public class ProxyFactory { private ProxyFactory(){ } private static ProxyFactory proxyFactory = new ProxyFactory(); public static ProxyFactory getInstance() { return proxyFactory; } /** * Jdk動態代理 * @param obj 委託對象 * @return 代理對象 */ public Object getJdkProxy(Object obj) { // 獲取代理對象 return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null; // 寫加強邏輯 System.out.println("中介(代理)收取服務費3000元"); // 調用原有業務邏輯 result = method.invoke(obj,args); System.out.println("客戶信息賣了3毛錢"); return result; } }); } /** * 使用cglib動態代理生成代理對象 * @param obj 委託對象 * @return */ public Object getCglibProxy(Object obj) { return Enhancer.create(obj.getClass(), new MethodInterceptor() { @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { Object result = null; System.out.println("中介(代理)收取服務費3000元"); result = method.invoke(obj,objects); System.out.println("客戶信息賣了3毛錢"); return result; } }); } }
package designpattern.proxy.dynamicproxy; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; /** * @author 應癲 */ public class CglibProxy { public static void main(String[] args) { RentingHouseImpl rentingHouse = new RentingHouseImpl(); // 委託對象 // 獲取rentingHouse對象的代理對象, // Enhancer相似於JDK動態代理中的Proxy // 經過實現接口MethodInterceptor可以對各個方法進行攔截加強,相似於JDK動態代理中的InvocationHandler // 使用工廠來獲取代理對象 RentingHouseImpl cglibProxy = (RentingHouseImpl) ProxyFactory.getInstance().getCglibProxy(rentingHouse); cglibProxy.rentHosue(); } }
再來一個JDK動態代理的實例:函數
package com.example.jdkproxy; public interface Person { public void dosomething(); }
package com.example.jdkproxy; public class Bob implements Person{ @Override public void dosomething() { System.out.println("Bob do something."); } }
package com.example.jdkproxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * @author liuyj * @Title: JDKDynamicProxy * @create 2020-06-02 17:30 * @ProjectName test * @Description: JDK動態代理 */ public class JDKDynamicProxy implements InvocationHandler { //聲明被代理的對象 private Person person; //構造函數 public JDKDynamicProxy(Person person) { this.person = person; } //獲取代理對象 public Object getTarget(){ Object proxyInstance = Proxy.newProxyInstance(person.getClass().getClassLoader(), person.getClass().getInterfaces(), this); return proxyInstance; } //代理對象執行方法的時候都會執行此方法 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("對原方法進行前置加強。"); //原方法執行 Object invoke = method.invoke(person, args); System.out.println("對原方法進行後置加強。"); return invoke; } }
package com.example.jdkproxy; public class ProxyTest { public static void main(String[] args) { System.out.println("不使用代理類。。。"); Person person=new Bob(); person.dosomething(); System.out.println("--------------"); System.out.println("使用代理類。。。"); Person proxy = (Person) new JDKDynamicProxy(new Bob()).getTarget(); proxy.dosomething(); } }