Created
December 19, 2018 14:56
-
-
Save MrFant/e9615ce68cf11cd1d3a5a95ae705cbf3 to your computer and use it in GitHub Desktop.
java代理模式之静态代理和动态代理
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* java 静态代理,基于接口实现 | |
*/ | |
public interface Hello { | |
String sayHello(String str); | |
} | |
class HelloImp implements Hello{ | |
// 目标对象 | |
public String sayHello(String str) { | |
return "HelloImp: "+str; | |
} | |
} | |
class StaticProxiedHello implements Hello{ | |
// 代理对象 | |
// 静态代理需要代理对象和目标对象实现同一接口 | |
// 优点 是不修改目标对象的前提下拓展其功能 | |
// 缺点 是一旦接口发生更改,目标对象和代理对象都要更改。 | |
private Hello hello=new HelloImp(); | |
public String sayHello(String str) { | |
// 可以对方法进行拓展,加工 | |
System.out.println("you will say: "+str); | |
str=str.toUpperCase(); | |
return hello.sayHello(str); | |
} | |
public static void main(String[] args) { | |
StaticProxiedHello staticProxiedHello=new StaticProxiedHello(); | |
System.out.println(staticProxiedHello.sayHello("i love u")); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import net.sf.cglib.proxy.Enhancer; | |
import net.sf.cglib.proxy.MethodInterceptor; | |
import net.sf.cglib.proxy.MethodProxy; | |
import java.lang.reflect.Method; | |
/** | |
* Java 基于cglib 的动态代理,目标类不需要实现某个接口,可以直接动态拓展其功能 | |
* 但是需要外部包 | |
*/ | |
public class HelloConcrete { | |
public String sayHello(String str) { | |
return "HelloConcrete: " + str; | |
} | |
public static void main(String[] args) { | |
Enhancer enhancer=new Enhancer(); | |
enhancer.setSuperclass(HelloConcrete.class); | |
enhancer.setCallback(new MyMethodInterceptor()); | |
HelloConcrete helloConcrete=(HelloConcrete) enhancer.create(); | |
System.out.println(helloConcrete.sayHello("i love u")); | |
// System.out.println(helloConcrete); | |
} | |
} | |
// CGLIB动态代理 | |
// 1. 首先实现一个MethodInterceptor,方法调用会被转发到该类的intercept()方法。 | |
class MyMethodInterceptor implements MethodInterceptor { | |
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { | |
System.out.println("you are calling "+method.getName() +" method:"); | |
return methodProxy.invokeSuper(o,objects); | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* java 基于jdk的动态代理,代理对象可以不用实现相关接口了。 | |
*/ | |
import java.lang.reflect.*; | |
public interface ProxyHello { | |
void sayHello(String str); | |
} | |
class ProxyHelloImp implements ProxyHello{ | |
// 目标对象 | |
public void sayHello(String str) { | |
System.out.println(str); | |
} | |
} | |
class DynamicProxyHello implements InvocationHandler { | |
// 动态代理对象 | |
private Object target; | |
public DynamicProxyHello(Object target){ | |
this.target=target; | |
} | |
// 使用如下写法可以不实现InvocationHandler接口 | |
// public Object getProxyInstance(){ | |
// return Proxy.newProxyInstance(proxyHello.getClass().getClassLoader(),proxyHello.getClass().getInterfaces(), | |
// new InvocationHandler() { | |
// public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { | |
// System.out.println("before call specific method >>" + method.getName()); | |
// Object result = method.invoke(proxyHello, args); | |
// System.out.println("after call specific method >>" + method.getName()); | |
// return result; | |
// } | |
// }); | |
// } | |
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { | |
System.out.println("before call specific method >>" + method.getName()); | |
// 调用某个对象的方法,这个对象为目标对象 | |
Object result = method.invoke(target, args); | |
System.out.println("after call specific method >>" + method.getName()); | |
return result; | |
} | |
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { | |
// FIXME 设置jvm参数,使得代理类生成文件 | |
// System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true"); | |
ProxyHello proxyHello=new ProxyHelloImp(); | |
System.out.println(proxyHello); | |
//这里有两种写法,这里采用略微复杂的一种写法,这样更有助于理解。 | |
Class<?> proxyClass= Proxy.getProxyClass(ProxyHello.class.getClassLoader(),ProxyHello.class); | |
final Constructor<?> cons = proxyClass.getConstructor(InvocationHandler.class); | |
final InvocationHandler ih = new DynamicProxyHello(proxyHello); | |
// TODO 这里只能强制转换为接口类型,而不能转换为target类,因为创建的proxy类实例是继承至proxy类而实现了相关接口的 | |
ProxyHello GeneratedProxyHello=(ProxyHello) cons.newInstance(ih); | |
GeneratedProxyHello.sayHello("i love u"); | |
// 简易写法,也是常用写法 | |
// ProxyHello GeneratedProxyHello= (ProxyHello)Proxy.newProxyInstance(proxyHello.getClass().getClassLoader(), | |
// proxyHello.getClass().getInterfaces(), | |
// new DynamicProxyHello(proxyHello)); | |
// 三个参数的意义如下: | |
// | |
// loader,指定代理对象的类加载器; | |
// interfaces,代理对象需要实现的接口,可以同时指定多个接口; | |
// handler,方法调用的实际处理者,代理对象的方法调用都会转发到这里 。 | |
// 这里输出GeneratedProxyHello的值会发现这个对象和proxyHello是一样的,因为会代理目标对象的toString()方法 | |
// System.out.println(GeneratedProxyHello); | |
// GeneratedProxyHello.sayHello("i love u"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment