JDK動態代理主要用到Proxy
類和InvocationHandler
接口,經過使用他們就能夠生成JDK動態代理類和動態代理對象。
Proxy提供以下兩個方法建立動態代理類和動態代理實例。java
public static Class<?> getProxyClass(ClassLoader loader,Class<?>...interfaces)
:建立一個動態代理類對應的Clas對象,該代理類將實現了interfaces接口。第一個Classloader參數指生成被代理類或接口的類加載器。ide
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
:直接建立一個動態代理對象,該代理對象的實現類實現了interfaces所指定的接口,執行代理對象的每一個方法都會被替換執行InvocationHandler對象的invoke方法。測試
下面做了一個演示,其中對象foo是由Proxy
的getProxyClass
方法先建立一個動態代理類的Clas對象,再建立動態代理實例,對象foo1是由Proxy
的newProxyInstance
直接建立一個動態代理實例。this
/** * Created by SqMax on 2018/4/25. */ interface Foo { void info(); } public class ProxyClassTest { public static void main(String[] args) throws Exception { Class proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), new Class[]{Foo.class}); Constructor constructor = proxyClass.getConstructor(new Class[]{InvocationHandler.class}); Foo foo = (Foo) constructor.newInstance(new Object[]{ new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("executing method:" + method); return null; } } }); Foo foo1 = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(), new Class[]{Foo.class}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("executing method:" + method); return null; } }); foo.info(); foo1.info(); } }
上面程序執行結果以下:代理
executing method:public abstract void top.sqmax.chapter18.Foo.info() executing method:public abstract void top.sqmax.chapter18.Foo.info()
有以下接口和類:code
public interface Dog { void info(); void run(); }
public class GunDog implements Dog { @Override public void info() { System.out.println("i am a gundog."); } @Override public void run() { System.out.println("i am running."); } }
想要在GunDog的info和run方法執行前和執行後執行一些通用的動做method1,method2()。對象
public class DogUtil { public void method1(){ System.out.println("---mock first common method---"); } public void method2(){ System.out.println("---mock second common method2----"); } }
能夠使用動態代理。接口
public class MyProxyFactory { public static Object getProxy(Object target){ return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),new InvocationHandler(){ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { DogUtil du=new DogUtil(); du.method1(); Object result=method.invoke(target,args); du.method2(); return result; } }); } }
下面測試,生成對GunDog的動態代理實例。ssl
public class Test { public static void main(String[] args) { Dog target = new GunDog(); Dog dog = (Dog) MyProxyFactory.getProxy(target); dog.info(); dog.run(); } }
執行結果get
---mock first common method--- i am a gundog. ---mock second common method2---- ---mock first common method--- i am running. ---mock second common method2----
Cglib動態代理是第三方技術,他的優點在於不須要提供接口,只要一個非抽象類能實現動態代理。Cglib動態代理的兩個關鍵類是Enhancer,MethodInterceptor。
使用Cblib動態代理首先要引入第三方的jar包:
<!-- https://mvnrepository.com/artifact/cglib/cglib --> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2.2</version> </dependency>
下面是一個具體的使用例子:
public class CglibProxy implements MethodInterceptor { public Object getProxy(Class cls) { Enhancer enhancer=new Enhancer(); enhancer.setSuperclass(cls); enhancer.setCallback(this); return enhancer.create(); } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("在調度真實對象前的服務"); Object result = methodProxy.invokeSuper(o, objects); System.out.println("在調度真實對象以後的服務"); return result; } public static void main(String[] args) { CglibProxy cglibProxy=new CglibProxy(); HelloWorld proxy = (HelloWorld) cglibProxy.getProxy(HelloWorldImpl.class); proxy.sayHelloWorld(); } }
上面的Enhancer的setSuprclas()方法代表是爲了那個類(被代理類)設置加強,setCallback()設置那個類去爲它代理。
輸出結果以下:
在調度真實對象前的服務 hello world 在調度真實對象以後的服務