java中的静态代理和动态代理,入门整理

静态代理和动态代理主要解决的问题是:在直接访问对象时带来的问题,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。

静态代理在感觉上和装饰设计模式很像

  1)、在代理类中实现被代理类实现的所有接口,这样保证了被代理类所能实现的方法,代理类也能实现,保证了两边行为的一致性,代理类就能转型为被代理类,当作被代理类处理。而代理中有被代理类的对象,这样,在代理类的内部实现接口方法时就能调用被代理类的方法,从而进行对被代理类的封装。

简单的示范:

package cn.edu.cjl;

public interface Subject {
        public void replace();
}

  

package cn.edu.cjl;

public class RealSubject implements Subject{

        @Override
        public void replace() {
                // TODO Auto-generated method stub
                System.out.println("real subject...");
        }

}

  

package cn.edu.cjl;

public class daili implements Subject {
        RealSubject subject;
        @Override
        public void replace() {
                System.out.println("before...");
                if(subject==null){
                        subject=new RealSubject();
                }
                subject.replace();
                System.out.println("after...");
        }

}

  

package cn.edu.cjl;

public class Client {
        public static void main(String[] args) {
                Subject subject=new daili();
                subject.replace();
        }
}

 代码中定义接口Subject,真实的实现类是RealSubject,但是在在主方法中调用的是daili类,在daili类中同样实现了Subject接口,但是真实上调用的是RealSubject类的方法。这就是静态代理。

  静态代理可以解决直接访问类方法带来的问题,但是本身也有问题,就是当大量的使用静态代理时类的个数将双倍的增加,不利于程序的管理。

动态代理使用了反射技术,一个代理类可以为任意类提供代理。

  代理类必须实现InvocationHandler接口,对代理实例调用方法时,将对方法调用进行编码并将其指派到它的代理程序的 invoke 方法。

  invoke方法运用反射技术,通过java.lang.reflect.Proxy类中提供的静态方法 newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序,也就是代理类实现的InvocationHandler接口中的invoke方法中,这个方法的各个参数的意思是

ClassLoader loader:类加载器,定义代理类的类加载器,可以任意指定。

Class<?>[] interfaces: 被代理类所实现的所有接口的class数组,可以用class对象的getInterfaces()方法得到。

InvocationHandler h:实现了InvocationHandler接口的对象。

简单的事例:

package cn.edu.cjl.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class proxy implements InvocationHandler {
        private Object object;
        public proxy(Object obj){
                this.object=obj;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                        throws Throwable {
                System.out.println("before");
                Object resultObject= method.invoke(object, args);
                System.out.println("after");
                return resultObject;
        }

}

  

package cn.edu.cjl.proxy;

import java.lang.reflect.Proxy;

public class Client {
        public static void main(String[] args) {
                Subject subject = null;
                RealSubject rSubject = new RealSubject();
                proxy proxy = new proxy(rSubject);
                subject = (Subject) Proxy.newProxyInstance(Client.class
                                .getClassLoader(), rSubject.getClass().getInterfaces(), proxy);
                subject.replace();
        }
}