动态代理最关键的本质:1.反射 2.多态
动态代理实现时 代码的关键:1.实现InvocationHandler 2. Proxy.newProxyInstance创建动态代理对象
通过反射拿到被代理对象的 信息 即可实现有关方法的调用。
通过多态 子类对象 赋值给 父类(接口)引用 调用的是子类重写的方法(如果有的话)。
1.通过动态代理,我们可以实现对 被代理对象调用方法的前后对相关信息进行处理(动态的修改或验证)
2.因为代理的对象是动态的,调用的方法是动态的,所以在调用的方法前后可以固定一些业务代码
理解动态代理的思路对后面各种框架的学习非常有好处。
上代码
package top.demo.test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import javax.naming.event.ObjectChangeListener;
//测试类
public class Test {
public static void main(String argv[]) {
You y=new You();
RealProxy proxyObj=new RealProxy();
Person proxy=(Person)proxyObj.getProxy(y);
proxy.hand();
}
}
//接口 规定了 被代理者需要实现的方法
interface Person{
public void hand();
}
//被代理者 实现了接口的方法
class You implements Person{
@Override
public void hand() {
System.out.println(" hit dog");
}
}
//动态代理类 实现调用处理接口
class MyProxy implements InvocationHandler{
//被代理者对象声明
private Object implementObj;
public Object getProxy(Object obj) {
//传入要被代理的对象
this.implementObj=obj;
/*
* * @param loader the class loader to define the proxy class
* @param interfaces the list of interfaces for the proxy class
* to implement
* @param h the invocation handler to dispatch method invocations to
* @return a proxy instance with the specified invocation handler of a
* proxy class that is defined by the specified class loader
* and that implements the specified interfaces
*
* */
//创建动态代理对象并返回 传入被代理的类型 被代理类实现的接口
//,以及 对这些接口调用时 的处理者(动态代理对象)(或者说 谁真正去调用被代理对象的方法)
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(!before(method,args))
{
return null;
}
//动态代理 调用被代理对象的方法
//每一个动态代理方法被调用,实际都需要被代理的对象去做,因为被代理对象才实现了 接口的方法
Object res=method.invoke(implementObj, args);
after(res);
return res;
}
public boolean before(Method method, Object[] args)
{
//需要在被代理对象方法被调用前做的方法
//可以对参数进行修改 等等
return true;
}
public void after(Object res) {
//需要在被代理对象方法被调用后做的方法
//可以对结果进行修改
}
}
//动态代理类 重写调用前后两个方法
class RealProxy extends MyProxy{
@Override
public boolean before(Method method, Object[] args) {
System.out.println("at method before");
return true;
}
@Override
public void after(Object res) {
System.out.println("at method after");
}
}