概念说明
代理模式是常用的设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等.即我们访问实际对象时是通过代理对象来访问的,实例的访问是在代理对象内部调用完成的。
Proxy类,保存一个引用使得代理可以访问实体,并提供一个与实体相同的接口,这样代理就可以用来代替实体
静态代理
编译时就已经将接口,被代理类,代理类等确定下来
需要三个类,共有接口,代理实现类,委托实现类(被代理类),代理与委托实现共同接口
接口
interface Test {
void test();
}
代理类
class TestReal implements Test{
private String name;
public TestReal(String name){
this.name = name;
}
@Override
public void test(){
System.out.println(name+"完成调用.");
}
}
委托类
class TestProxy implements Test{
TestReal testReal;
public TestProxy(Test test){
this.testReal = (TestReal)test;
}
@Override
public void test(){
testReal.test();
}
}
测试
public static void main(String[] args){
Test real = new TestReal("阿西吧");
Test proxy = new TestProxy(real);
proxy .test();
}
代理模式就是在访问实际对象时引入一定程度的间接性,因为这种间接性,可以附加多种用途。这里的间接性就是指不直接调用实际对象的方法,那么我们在代理过程中就可以加上一些其他用途。
动态代理
概念:代理类在程序运行时创建的代理方式被成为动态代理。相比于静态代理,动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类中的方法。
在java的java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过这个类和这个接口可以生成JDK动态代理类和动态代理对象。
-
创建一个InvocationHandler对象
//创建一个与代理对象相关联的InvocationHandler
//real为委托对象
InvocationHandler realHandler = new MyInvocationHandler<Test>(real); -
使用Proxy类的getProxyClass静态方法生成一个动态代理类ProxyClass
Class<?> ProxyClass = Proxy.getProxyClass(Test.class.getClassLoader(),newClass<?>[]{Test.class}); -
获得ProxyClass中一个带InvocationHandler参数的构造器constructor
Constructor<?> constructor = ProxyClass.getConstructor(InvocationHandler.class); -
通过构造器constructor来创建一个动态实例Proxy
Test proxy=(Test)cons.newInstance(realHandler);接口 interface Test { void test(); } 委托类 class TestProxy implements Test{ TestReal testReal; public TestProxy(Test test){ this.testReal = (TestReal)test; } @Override public void test(){ testReal.test(); } } class MyInvocationHandler<T> implements InvocationHandler{ //invocationHandler持有的被代理对象 T target; public MyInvocationHandler(T target){ this.target = target; } //proxy:代表动态代理对象 //method:代表正在执行的方法 //args:代表调用目标方法时传入的实参 @Override public Object invoke(Object proxy,Method method,Object[] args) throws Throwsble{ System.out.println("代理执行"+method.getName()+"方法。"); //代理过程中插入检测方法 System.out.println("监测开始..."); Object result = method.invoke(target, args); System.out.println("监测结束..."); return result; } } 简化创建动态代理对象 public static void main(String args){ //创建实例对象,为被代理对象 Test real = new TestReal("阿西吧"); //创建一个与代理对象相关联的invocationHandler InvocationHandler realHandler = new MyInvocationHandler<Test>(real); //创建一个代理对象proxy来代理real,代理对象的每个执行方法都会替换执行InvocationHandler中的invoke方法 Test proxy =(Test) Proxy.newProxyInstance(Test.class,getClassLoader(),new Class<?>[]{Test.class},realHandler); }
newProxyInstance动态代理实际原理,在创建代理对象时,就是通过反射获得这个类的构造方法,然后创建的代理实例
以上动态代理为接口形式的动态代理,所以也就决定了java动态代理只能对接口进行代理,Java的继承机制注定了这些动态代理类们无法实现对class的动态代理。(AOP的一个简单实现)
网友评论