先说结论:
1、通过newProxyInstance创建真实的代理类,其第三个参数设置关联了实现InvocationHandler接口的类。
2、实现了InvocationHandler接口的类中提供invoke方法,供真实的代理类通过反射调用方法,并修改业务逻辑。
1、准备
创建接口---->
public interface people {
void sayHello(String name);
void working(String work);
}
创建接口的实现类—>
public class Student implements people{
public void sayHello(String name) {
System.out.println("Hello! "+name);
}
public void working(String work) {
System.out.println("i'm "+work);
}
}
创建继承了InvocationHandler对象的动态代理类---->
三个作用
1、初始化被代理类
2、创建真实代理类,与本类关联
3、真实代理类调用方法时,从invoke方法通过反射调用实际方法
public class JDKDynamicProxy implements InvocationHandler {
//target为被代理的目标对象,作为构造方法的参数被初始化
private Object target;
public JDKDynamicProxy (Object target){
this.target = target;
}
//使用Proxy的newProxyInstance方法,返回一个代理类对象
@SuppressWarnings("Unchecked")
public <T> T getProxy(){
return (T) Proxy.newProxyInstance(
target.getClass().getClassLoader(),//生成该代理类对象的类加载器,用来加载代理类
target.getClass().getInterfaces(),//获取实现类的interface对象数组,代理类对象可以调用接口中的方法
this); //生成的动态代理对象调用方法时所关联到的InvocationHandler对象
}
// @Override 接口不能@Override
//com.sun.proxy.$Proxy0对象在客户端调用方法时,调用newProxyInstance的第三个参数即实现InvocationHandler对象的invoke方法
//invoke三个参数----JRE注入
// proxy-->真实的代理对象 com.sun.proxy.$Proxy0
//真实的代理对象不是this,this是JDK动态代理.JDKDynamicProxy
//method-->所调用对象的方法的Method对象
//args-->方法的参数
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(proxy.getClass().getName());
System.out.println(this.getClass().getName());
before();
Object result;
if(method.getName().equals("sayHello")){
System.out.println("调用了sayHello");
//反射,方法的Method对象的invoke方法,输入方法的对象和方法参数,调用该方法
result = method.invoke(target,args);
}else {
System.out.println("调用了work");
result = method.invoke(target,args);
}
after();
return result;
}
private void before(){
System.out.println("before 动态代理");
}
private void after(){
System.out.println("after 动态代理");
}
}
2、客户端调用:
创建实现类的实例对象---->
people peopleImp = new Student();//创建实现类
创建动态代理类的实例,把实现类对象作为参数,包装实现类---->
JDKDynamicProxy jdkDynamicProxy = new JDKDynamicProxy(peopleImp);
**
创建动态代理真实对象
**
啥是真实动态代理对象?
在代理类中invoke方法下写入
System.out.println(proxy.getClass().getName());
System.out.println(this.getClass().getName());
得到输出结果
com.sun.proxy.$Proxy0
JDK动态代理.Student
即:第一个输出结果是newProxyInstance方法创建的真实动态代理对象
第二个是实现了InvocationHandler接口的对象
注意第三个参数,即生成的真实动态代理对象调用方法时所关联到的InvocationHandler对象
people peopleProxy = (people) Proxy.newProxyInstance(
peopleImp.getClass().getClassLoader(),
peopleImp.getClass().getInterfaces(),
jdkDynamicProxy);
动态代理真实对象(com.sun.proxy.$Proxy0)调用其使用newProxyInstance方法创建时的第三个参数,即实现了InvocationHandler接口的对象(JDK动态代理.Student)的invoke方法,通过反射实现方法调用。