JDK 内置的 Proxy 实现动态代理
JDK内置的动态代理只能够代理实现接口的类,因此需要先提供一个接口
1 2 3 4
| public interface Interface { void doSomething(); void somethingElse(String arg); }
|
实现类:
1 2 3 4 5 6 7 8 9 10 11
| public class RealObject implements Interface { @Override public void doSomething() { System.out.println("doSomething"); }
@Override public void somethingElse(String arg) { System.out.println("something " + arg); } }
|
实现一个动态代理类,该类实现接口 InvocationHandler
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class DynamicProxyHandler implements InvocationHandler { private Object proxied; public DynamicProxyHandler(Object proxied){ this.proxied = proxied; }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("**** proxy: " + proxy.getClass() + ", method: " + method + ", args:" + args); if (args != null) for (Object arg : args) System.out.println(" " + arg); return method.invoke(proxied, args); } }
|
测试运行:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class SimpleDynamicProxy{ public static void consumer(Interface iface){ iface.doSomething(); iface.somethingElse("bonobo"); }
public static void main(String[] args) { RealObject real = new RealObject(); consumer(real);
Interface proxy = (Interface) Proxy.newProxyInstance( Interface.class.getClassLoader(), new Class[]{Interface.class}, new DynamicProxyHandler(real)); consumer(proxy); } }
|
使用内置的 Proxy 实现动态代理存在一个问题:被代理的类必须实现接口,未实现接口则无法完成动态代理
如果项目中有些类没有实现接口,则不应该为了实现动态代理而可以去抽出一些没有实际意义的接口,但我们可以使用cglib解决该问题 。
使用 cglib 实现动态代理
CGLIB(Code Generation Library)是一个开源项目,是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口,通俗说cglib可以在运行时动态生成字节码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| public class DynamicProxy implements MethodInterceptor {
Object proxied;
public Object getProxyObject(Object proxied){ this.proxied = proxied; Enhancer enhancer = new Enhancer(); enhancer.setCallback(this); enhancer.setSuperclass(proxied.getClass()); return enhancer.create(); }
@Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { Object result = methodProxy.invoke(proxied, objects);
return result; } }
|
测试:
1 2 3 4
| public static void main(String[] args) { Interface iface = (Interface) new DynamicProxy().getProxyObject(new RealObject()); iface.doSomething(); }
|
intercept 方法的参数:
- Object o :cglib 动态生成的代理类。
- Method method :实体类被调用的被代理的方法。
- Object[] objects :参数值列表
- MethodProxy methodProxy :生成的代理类对方法代理的代理引用
小结
使用 cglib 可以实现动态代理,即使被代理的类没有实现接口,但被代理的类必须不是 final 类。