interface TargetInterface{
//目标类接口
public void method1();
public String method2();
}
class Target implements TargetInterface{
//实现目标类
@Override
public void method1(){
System.out.println("目标对象方法method1");
}
@Override
public String method2(){
System.out.println("目标对象方法method2");
return "method2";
}
}
class ProxyTest{
@Test
public void test1(){
//获得动态代理对象-----在运行时 在内存中动态的为Target创建一个虚拟的代理对象
//objProxy是代理对象 根据参数确定到底是谁的代理对象
TargetInterface objProxy = (TargetInterface)Proxy.newProxyInstance(
Target.class.getClassLoader(),//与目标对象的类加载器
new Class[]{TargetInterface.class},
new InvocationHander(){
//invoke 代表的是执行代理对象的方法
@Override
//method:代表目标对象的方法字节码对象
//args:代表目标对象的响应的方法参数
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
System.out.println("执行目标对象方法前的逻辑代码")
//这个invoke不同上面的,只是名字刚好相同,
//此是执行目标对象的方法
//具体Object invoke(Object obj, Object[] args)
//obj为要执行此方法的对象(需要被代理的对象),args方法里的参数
Object arg = method.invoke(new Target(), args);
System.out.println("执行目标对象方法后的逻辑代码")
return arg;
}
}
);
objProxy.method1();//实质调用invoke
String method = objProxy.method2();
System.out.println(method);
}
}
写InterfaceTarget接口的目的是因为生成代理对象需要用到
Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h)//返回值是Object类型
- 参数1:loader,类加载器,动态代理类运行时创建,任何类都需要类加载器将其加载到内存。一般情况:
- 当前类.class.getClassLoader();
- 目标类实例.getClass().getClassLoader();
- 参数2:interfaces 代理类需要实现的所有接口
- 方式一:目标类实例.getClass().getInterfaces();!注意,只能获得自己接口,不能获得父元素接口
- 方式二:new Class[]{目标类.class}
例如:jdbc驱动–>DriverManger 获得接口Connection
- 参数3:InvocationHandler 处理类,接口必须进行实现类,一般采用匿名内部
- 提供invoke方法,代理类的每一个方法执行时,都将调用一次invoke
Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHander(){
@Override
//执行几次?----->看代理对象调用方法几次
//代理对象调用接口相应方法都是调用invoke方法
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
return null;
}
}
);
参数1:Object proxy:代理对象
参数2: Method method:代理对象当前执行的方法的描述对象(反射)
- 执行方法名:method.getName()
- 执行方法:method.invoke(对象,实际参数)
参数3:Object[] args:方法实际参数
Object invoke(Object proxy,
Method method,
Object[] args)
throws Throwable
注意:JDK的Proxy方式实现的动态代理 目标对象必须有接口 没有接口不能实现jdk版的动态代理
个人理解:Proxy类里面通过Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h)方法通过传入参数interfaces实现了全部的接口并且额外实现了InvocationHandler ,此接口有invoke方法,里面通过传入目标对象、目标对象的方法对象、和参数对接口里的方法实现动态代理。(invoke方法本质是目标对像.相应方法()+ 其他逻辑代码,此逻辑代码就写在重写的invoke里面)