动态代理的作用
可以在方法前后做统一的处理,比如:事务处理、日志统计
目标
理解动态代理原理,实现代理工厂。
准备
可以看出真正代理的是接口,动态执行方法的时候才是反射调用被代理类的方法。
jdk动态代理是基于接口的。所以被代理的类必须实现接口。
1.Proxy类的静态方法,创建代理实例
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
参数说明:
loader 被代理类的类加载器
interfaces 被代理类的所有接口
h 代理实例处理器
2.InvocationHandler 代理实例接口的唯一方法
public Object invoke(Object proxy, Method method, Object[] args)
proxy 代理类对象
method 被代理类接口方法
args 被代理类接口方法参数
代码
代理工厂ProxyFactory
package org.example.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @ClassName ProxyFactory
* @Description 代理类工厂
* @Author xuxiang
* @Date 15:05 2022/6/14
**/
public class ProxyFactory {
private Object object;
public ProxyFactory(Object object){
this.object = object;
}
InvocationHandler invocationHandler = new InvocationHandler(){
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("执行方法前");
Object invoke = method.invoke(object, args);
System.out.println("执行方法后");
return invoke;
}
};
public Object newInstance(){
return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), invocationHandler);
}
}
被代理接口IProxy
package org.example.proxy;
/**
* @ClassName IProxy
* @Description
* @Author xuxiang
* @Date 15:19 2022/6/14
**/
public interface IProxy {
public void test(String ccc);
public void test1();
}
被代理类 ProxyTest
package org.example.proxy;
/**
* @ClassName proxyTest
* @Description
* @Author xuxiang
* @Date 15:04 2022/6/14
**/
public class ProxyTest implements IProxy{
@Override
public void test(String ccc){
System.out.println("test方法!");
}
@Override
public void test1(){
System.out.println("test1方法!");
}
}
测试 App
package org.example;
import org.example.proxy.IProxy;
import org.example.proxy.ProxyFactory;
import org.example.proxy.ProxyTest;
import org.example.proxy.ProxyTest2;
import java.math.BigInteger;
/**
* Hello world!
*
*/
public class App
{
public static void main( String[] args )
{
ProxyTest proxyTest = new ProxyTest();
ProxyFactory proxyFactory = new ProxyFactory(proxyTest);
IProxy proxy = (IProxy)proxyFactory.newInstance();
proxy.test("d");
proxy.test1();
}
}
执行结果:
重点
Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), invocationHandler);
这个方法会返回一个代理类对象,这个代理类对象,会继承Proxy类并且实现被代理对象的接口。当调用接口方法的时候,会回调我们传入到Proxy对象里面的invocationHandler的invoke方法。
invoke方法的method参数通过反射调用原方法。
测试加上
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
可以把生成的代理类对象的class文件保存在本地,默认是项目路径下的com.sun.proxy包下。
package org.example;
import org.example.proxy.ProxyImpil;
import org.example.proxy.ProxyFactory;
import org.example.proxy.ProxyTest;
import org.example.proxy.ProxyTest2;
/**
* Hello world!
*
*/
public class App
{
public static void main( String[] args )
{
//将生成的代理对象的字节码文件 保存到硬盘
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
ProxyTest proxyTest = new ProxyTest();
ProxyFactory proxyFactory = new ProxyFactory(proxyTest);
ProxyImpil proxy = (ProxyImpil)proxyFactory.newInstance();
proxy.test("d");
proxy.test1();
}
}
看一下生成出来的类就很清楚了。
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.sun.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import org.example.proxy.ProxyImpil;
public final class $Proxy0 extends Proxy implements ProxyImpil {
private static Method m1;
private static Method m2;
private static Method m4;
private static Method m3;
private static Method m0;
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void test1() throws {
try {
super.h.invoke(this, m4, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void test(String var1) throws {
try {
super.h.invoke(this, m3, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m4 = Class.forName("org.example.proxy.ProxyImpil").getMethod("test1");
m3 = Class.forName("org.example.proxy.ProxyImpil").getMethod("test", Class.forName("java.lang.String"));
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}