package learn;
import javafx.beans.binding.ObjectExpression;
import java.lang.annotation.Target;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* JDK动态代理
*/
interface TargetOne {
void action();
}
interface TargetTwo {
void action2();
}
class TargetOneImpl implements TargetOne{
@Override
public void action() {
System.out.println("TargetOneImpl实现TargetOne接口的方法...action");
}
}
class TargetTwoImpl implements TargetTwo{
@Override
public void action2() {
System.out.println("TargetTwoImpl实现TargetTwo接口的方法...action2");
}
}
class TargetAllImpl implements TargetOne,TargetTwo{
@Override
public void action() {
System.out.println("TargetAllImpl实现TargetOne接口的方法...action");
}
@Override
public void action2() {
System.out.println("TargetAllImpl实现TargetTwo接口的方法...action2");
}
/**
* 不是实现的接口的方法,动态代理类里面是没有此方法的,无法代理
*/
public void action3(){}
}
/**
* 动态代理工厂
*/
class DynamicProxy implements InvocationHandler {
/**
* 接口的一个引用,多态的特性会使得在程序运行的时候,它实际指向的是实现它的子类对象
* object本身只是一个引用,具体指向哪个实现类是我们自己设定的
*/
private Object object;
DynamicProxy(){
object=null;
}
DynamicProxy(Object object){
this.object=object;
}
public Object getObject(){
return this.object;
}
public void setProxyInterfaceImpl(Object object) {
this.object = object;
}
/**
* 获取动态代理类的实例
*/
public Object getProxyExample() {
/**
* 使用Proxy类的静态方法newProxyInstance方法,将代理对象替换为this.object所引用的实现类
public static Object newProxyInstance(ClassLoader loader, //需要被代理的实现类的类加载器
Class<?>[] interfaces, //需要被代理的实现类实现的接口
InvocationHandler h) //实现InvocationHandler代理类的对象
*
* 返回值是Proxy类的实例,这个实例实现了传入的实现类所实现的接口
*/
return Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),this);
}
/**
* 设置代理实现类
* 获取动态代理类的实例
*
* ①将object指向实际实现接口的子类对象
* ②根据被代理类(接口实现类)返回一个代理类对象
*
*/
public Object getProxyExample(Object object) {
this.object = object;
return Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),this);
}
/**
* 当通过代理类的对象发起对接口被重写的方法的调用的时候,都会转换为对invoke方法的调用,
* 甚至是调用一些实现类的继承的Object的方法也会跳进来,类似于toString
* 入参proxy就是Proxy.newProxyInstance获取到的动态代理类
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
/**
* 静态代理存在的问题:如果不使用反射的情况下,调用具体方法,需要传入具体的接口,既然要传入具体接口,那就不能使用object做为公共引用
* 因为你是在运行前就决定了要代理哪个接口的哪个方法,如果使用Object引用,你是调不了具体接口的方法的;
*
* 动态代理就可以使用Object作为公共引用,因为Object引用的具体实现类是在运行时决定的,这是一个动态绑定的多态(父类引用到底使用的是
* 哪个实现类,是在运行时决定的)由此还可以在运行时通过反射获取这个实际的被代理的实现类(Proxy类的静态方法newProxyInstance方法
*
*
Object object=new Object();
System.out.println("调用对象:"+proxy.getClass().getName());
System.out.println(proxy.getClass().getName()+"相对于Object多出的的方法列表:");
Set<String> set=new HashSet<>();
for(Method method1:object.getClass().getMethods()){
set.add(method1.getName());
}
for(Method method1:proxy.getClass().getMethods()){
if(!set.contains(method1.getName()))System.out.println(method1.getName());
}
输出:
调用对象:learn.$Proxy0
learn.$Proxy0相对于Object多出的的方法列表:
action
isProxyClass
getInvocationHandler
getProxyClass
newProxyInstance
*
* 我们可以轻松得出结论,调用action方法的不是实现类本身,而是通过动态代理生
* 成的learn.$Proxy0类来进行的方法调用,传入不同的实现类,只是给$Proxy0添
* 加了不同接口的方法;
* 这也说明了,不仅是接口的方法会传入invoke执行,代理类$Proxy0有的方法都会
* 进入invoke;
*/
/**
* 这里的返回值,就相当于调用真正的实现类的方法的返回值,返回给实际调用者
*/
System.out.print("被代理执行:");
Object returnVal = method.invoke(this.object,args);
return returnVal;
}
}
public class JavaDynamicProxy {
public static void main(String[] args) throws Throwable {
/**
* 创建代理工厂
*/
DynamicProxy dynamicProxy=new DynamicProxy();
/**
* 通过反射获取实际被代理的接口实现类的代理类,这个代理类实现了相同的接口,用接口接收这个代理类后,就可以通过这个引用调用接口方法了
*/
/**
*
* TargetOne proxyOne=(TargetOne)dynamicProxy.getProxyExample();
* 注意:返回的是Object类型的引用(被引用的是反射获取的实现了相同接口的Proxy实例),需要强转
* 一下引用类型(因为反射获取的并不是实现类,所以只能转为接口,不能转实现类)不转的话是调不了方法的。
*
* dynamicProxy.getProxyExample(new TargetOneImpl()) instanceof TargetOne --->true
* dynamicProxy.getProxyExample(new TargetOneImpl()) instanceof Proxy --->true
* dynamicProxy.getProxyExample(new TargetOneImpl()) instanceof TargetOneImpl --->false
*
* 这样写就会报错
* TargetOne proxyOne=(TargetOneImpl) dynamicProxy.getProxyExample(new TargetOneImpl());
* 使用instanceof可以得知返回值是动态生成的Proxy类的实例,并且还实现了TargetOne接口,所以只能强转为接口类型
* (instanceof 测试左边的对象是否是右边的类的实例,返回 boolean 的数据类型)
*/
/**
* 传入具体代理的实现类
* 此时proxyOne实则指向的动态代理类$Proxy0
* 调用动态代理类的方法便会转入invoke
*/
dynamicProxy.setProxyInterfaceImpl(new TargetOneImpl());
TargetOne proxyOne=(TargetOne)dynamicProxy.getProxyExample();
System.out.println("生成的代理类:"+proxyOne.getClass().getName());
proxyOne.action();
System.out.println("---------------------------------------------");
dynamicProxy.setProxyInterfaceImpl(new TargetTwoImpl());
TargetTwo proxyTwo=(TargetTwo) dynamicProxy.getProxyExample();
System.out.println("生成的代理类:"+proxyTwo.getClass().getName());
proxyTwo.action2();
System.out.println("---------------------------------------------");
DynamicProxy dynamicProxy1=new DynamicProxy(new TargetAllImpl());
System.out.println("生成的代理类:"+dynamicProxy1.getProxyExample().getClass().getName());
((TargetOne) dynamicProxy1.getProxyExample()).action();
((TargetTwo) dynamicProxy1.getProxyExample()).action2();
System.out.println("---------------------------------------------");
/**
* 代理具体方法的时候可以直接用invoke方法自己通过反射获取并传入具体要代理的Method给invoke方法
*/
DynamicProxy dynamicProxy2=new DynamicProxy(new TargetAllImpl());
System.out.println("生成的代理类:"+dynamicProxy2.getProxyExample().getClass().getName());
dynamicProxy2.invoke(null,dynamicProxy2.getObject().getClass().getDeclaredMethod("action"), null);
dynamicProxy2.invoke(dynamicProxy2.getProxyExample(),dynamicProxy2.getObject().getClass().getDeclaredMethod("action2"), null);
System.out.println("---------------------------------------------");
/**
* 检验Class对象的创建规则
*/
DynamicProxy dynamicProxy3=new DynamicProxy(new TargetOneImpl());
DynamicProxy dynamicProxy4=new DynamicProxy(new TargetOneImpl());
System.out.println("相同实现类的代理Class对象是否相等:"+dynamicProxy3.getProxyExample().getClass().getName().equals(dynamicProxy4.getProxyExample().getClass().getName()));
System.out.println("相同实现类的代理实例是否相等:"+dynamicProxy3.equals(dynamicProxy4));
System.out.println("---------------------------------------------");
/**
* 输出:
*
* 生成的代理类:learn.$Proxy0
* 被代理执行:TargetOneImpl实现TargetOne接口的方法...action
* ---------------------------------------------
* 生成的代理类:learn.$Proxy1
* 被代理执行:TargetTwoImpl实现TargetTwo接口的方法...action2
* ---------------------------------------------
* 生成的代理类:learn.$Proxy2
* 被代理执行:TargetAllImpl实现TargetOne接口的方法...action
* 被代理执行:TargetAllImpl实现TargetTwo接口的方法...action2
* ---------------------------------------------
* 生成的代理类:learn.$Proxy2
* 被代理执行:TargetAllImpl实现TargetOne接口的方法...action
* 被代理执行:TargetAllImpl实现TargetTwo接口的方法...action2
* ---------------------------------------------
* 相同实现类的代理Class对象是否相等:true
* 相同实现类的代理实例是否相等:false
* ---------------------------------------------
*
* Process finished with exit code 0
*
* 从输出还能看出,代理工厂生成代理类Class对象的类别是根据实现类生成,不同的实现类会生成不同的代理Class对象
* 但是每个工厂的实例是不一样的System.out.println(dynamicProxy2.equals(dynamicProxy1));
*/
}
}