Skip to content

Instantly share code, notes, and snippets.

@MrFant
Created December 19, 2018 14:56
Show Gist options
  • Save MrFant/e9615ce68cf11cd1d3a5a95ae705cbf3 to your computer and use it in GitHub Desktop.
Save MrFant/e9615ce68cf11cd1d3a5a95ae705cbf3 to your computer and use it in GitHub Desktop.
java代理模式之静态代理和动态代理
/**
* 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"));
}
}
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);
}
}
/**
* 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