动态代理机制:
1、在CalculatorProxy中的getProxy方法中,调用了 Proxy.newProxyInstance方法,并且传进去了一个
InvocationHandler匿名对象。
2、在使用到动态代理的时候,创建动态代理对象,创建动态代理对象的时候会动态的生成一个动态代理类,这个类
继承了Proxy,并且根据这个类创建出对象,这个动态代理类是直接存在内存中的,并不会写在硬盘上,在实例
化动态代理类的时候会把InvocationHandler匿名对象给到Proxy类(因为Proxy是它的父类)中的
InvocationHandler类型成员变量。
3、动态代理类中也有和原始类中方法名和参数都相同的方法(在此举例是动态代理类也实现了Calculator1接口),
但是****重点**** 动态代理类对象执行这些方法的时候是把传进来的参数调用了父类中InvocationHandler类型成员变量
的invoke方法来执行的,这也解释了为什么newProxyInstance方法要传入InvocationHandler匿名对象****重点**** 。
语法
1、核心部分
public Object getProxy(){
Object proxy;
ClassLoader loader = target.getClass().getClassLoader();
Class [] interfaces = target.getClass().getInterfaces();
/**
* 第一个参数: 类加载器,因为使用代理的时候需要用到目标对象对应类的类加载器
* 第二个参数:目标类的接口,让外边的调用方可以看到代理类“也有”目标类的方法
*/
proxy = Proxy.newProxyInstance(loader, interfaces, new InvocationHandler() {
// InvocationHandler这个对象是在动态代理对象执行的时候使用已经给到父类的作为成员变量InvocationHandler
// 的时候调用父类的InvocationHandler的invoke方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("目标方法 " + method.getName() + " 开始执行,其参数是" + Arrays.asList(args));
Object object = method.invoke(target, args);
System.out.println("目标方法执行结束, 返回值是" + object);
return object;
}
});
return proxy;
}
2、完整例子
package calculator;
public interface Calculator1 {
int add(int a, int b);
int sub(int a, int b);
}
package calculator;
public class CalculatorIImpl implements Calculator1 {
@Override
public int add(int a, int b) {
return a+b;
}
@Override
public int sub(int a, int b) {
return a-b;
}
}
package proxy;
import calculator.Calculator1;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
/**
* Demo class
*
* @author keriezhang
* @date 2016/10/31
*/
public class CalculatorProxy {
private Calculator1 target;
private CalculatorProxy calculatorProxy;
public CalculatorProxy(Calculator1 calculator1){
this.target = calculator1;
}
public Object getProxy(){
Object proxy;
ClassLoader loader = target.getClass().getClassLoader();
Class [] interfaces = target.getClass().getInterfaces();
/**
* 第一个参数: 类加载器,因为使用代理的时候需要用到目标对象对应类的类加载器
* 第二个参数:目标类的接口,让外边的调用方可以看到代理类“也有”目标类的方法
*/
proxy = Proxy.newProxyInstance(loader, interfaces, new InvocationHandler() {
// InvocationHandler这个对象是在动态代理对象执行的时候使用已经给到父类的作为成员变量InvocationHandler
// 的时候调用父类的InvocationHandler的invoke方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("目标方法 " + method.getName() + " 开始执行,其参数是" + Arrays.asList(args));
Object object = method.invoke(target, args);
System.out.println("目标方法执行结束, 返回值是" + object);
return object;
}
});
return proxy;
}
}
package calculator;
import proxy.CalculatorProxy;
/**
* 动态代理运行机制:
1、在CalculatorProxy中的getProxy方法中,调用了 Proxy.newProxyInstance方法,并且传进去了一个
InvocationHandler匿名对象。
2、在使用到动态代理的时候,创建动态代理对象,创建动态代理对象的时候会动态的生成一个动态代理类,这个类
继承了Proxy,并且根据这个类创建出对象,这个动态代理类是直接存在内存中的,并不会写在硬盘上,在实例
化动态代理类的时候会把InvocationHandler匿名对象给到Proxy类(因为Proxy是它的父类)中的
InvocationHandler类型成员变量。
3、动态代理类中也有和原始类中方法名和参数都相同的方法(在此举例是动态代理类也实现了Calculator1接口),
但是****重点**** 动态代理类对象执行这些方法的时候是把传进来的参数调用了父类中InvocationHandler类型成员变量
的invoke方法来执行的,这也解释了为什么newProxyInstance方法要传入InvocationHandler匿名对象****重点**** 。
*/
public class Main {
public static void main(String []args){
CalculatorIImpl calculatorI = new CalculatorIImpl();
Calculator1 calculator1 = (Calculator1) new CalculatorProxy(calculatorI).getProxy();
calculator1.add(1,2);
}
}