• 代理模式之Java动态代理 _ Java认证 _ 考试大
  • 发布时间:2012-10-26 17:03 | 作者: | 来源: | 浏览:
  •     1. Overview
        Java在java.lang.reflect包下,定义了自己的代理。利用这个包下的类,我们可以在运行时动态地创建一个代理类,实现一个或多个接口。并将方法的调用转发到你所指定的类。因为实际代理是在运行时创建的,所以称为:动态代理。

        Proxy:完全由java产生的,而且实现了完整的subject接口。
        InvocationHandler:Proxy上的任何方法调用都会被传入此类,InvocationHandler控制对RealSubject的访问。
        因为Java已经帮助我们创建了Proxy类,我们需要有办法告诉Proxy类你要做什么,我们不能像以前一样把代码写入到Proxy类中,因为Proxy类不是我们实现的。那么我们应该放在哪里?放在InvocationHandler类中,InvocationHandler类是响应代理的任何调用。我们可以吧InvocationHandler想成是代理收到方法调用后,请求做实际工作的对象。
        2. java.lang.reflect.InvocationHandler
        被代理实例所实现的一个接口,内部只有一个invoke()方法,签名如下;
        Java代码
        public Object invoke(Object proxy, Method method, Object[] args)
        当代理的方法被调用的时候,代理就会把这个调用转发给InvocationHandler,也就会调用它的invoke()方法。
        3. java.lang.reflect.Proxy
        提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类,我们经常使用的静态方式是:
        Java代码
        newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)
        4. 示例:
        情形:自己可以查看修改姓名性别,但是不能修改rate。他人可以查看姓名,性别以及修改rate,但是不能修改姓名性别。
        4.1 定义一个接口:
        Java代码
        public interface Person {
        String getName();
        String getGender();
        void setName(String name);
        void setGender(String gender);
        void setRate(int rate);
        int getRate();
        }
        4.2 定义实现Person接口类
        Java代码
        public class PersonImpl implements Person {
        String name;
        String gender;
        String interests;
        int rate;
        public String getName() {
        return name;
        }
        public void setName(String name) {
        this.name = name;
        }
        public String getGender() {
        return gender;
        }
        public void setGender(String gender) {
        this.gender = gender;
        }
        public String getInterests() {
        return interests;
        }
        public void setInterests(String interests) {
        this.interests = interests;
        }
        public int getRate() {
        return rate;
        }
        public void setRate(int rate) {
        this.rate = rate;
        }[nextpage]
        4.3 定义OwnerInvocationHandler类,表示如果为本人,则可以进行修改查看姓名性别。
        Java代码
        public class OwnerInvocationHandler implements InvocationHandler{
        private Person personBean;
        public OwnerInvocationHandler(Person personBean){
        this.personBean = personBean;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
        throws IllegalAccessException {
        try {
        if(method.getName().startsWith("get")){//如果方法名为get,就调用person类内的get相应方法
        return method.invoke(personBean, args);
        }else if(method.getName().equals("setRate")){ // 如果方法是setRate,则抛出异常
        throw new IllegalAccessException("access deny");
        }else if(method.getName().startsWith("set")){  //如果为set,就调用person类内的set相应方法
        return method.invoke(personBean, args);
        }else {
        System.out.println("non method invoke");
        }
        } catch (InvocationTargetException e) {
        e.printStackTrace();
        }
        return null;
        }
        }
        4.4 定义NonInvocationHandler类,表示如果不为本人,则可以进行查看姓名性别和修改rate。
        Java代码
        public class NonInvocationHandler implements InvocationHandler{
        //
        private Person person;
        public NonInvocationHandler(Person person){
        this.person = person;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable {
        if(method.getName().startsWith("setRate")){
        return method.invoke(person, args);
        }else if (method.getName().startsWith("get")){
        return method.invoke(person, args);
        } else {
        System.out.println("non method invoke");
        return null;
        }
        }
        }
        4.5 测试类MyDynamicProxy
        Java代码
        public class MyDynamicProxy {
        public Person getOwnerPersonBeanProxy(Person person){
        return (Person)Proxy.newProxyInstance(person.getClass().getClassLoader(),
        person.getClass().getInterfaces(), new OwnerInvocationHandler(person));
        }
        public Person getNonPersonBeanProxy(Person person){
        return (Person)Proxy.newProxyInstance(person.getClass().getClassLoader(),
        person.getClass().getInterfaces(), new NonInvocationHandler(person));
        }
        public static void main(String[] args) {
        MyDynamicProxy mdp = new MyDynamicProxy();
        mdp.test();
        }
        public void test(){
        //
        Person person = getPersonBeanFromDB1();
        Person personProxy = getOwnerPersonBeanProxy(person);
        System.out.println(personProxy.getName());
        try {
        personProxy.setRate(2);
        } catch (Exception e) {
        System.out.println("can not setRate");
        }
        //
        Person person1 = getPersonBeanFromDB1();
        Person personProxy2 = getNonPersonBeanProxy(person1);
        System.out.println(personProxy2.getName());
        personProxy2.setRate(2);
        System.out.println(personProxy2.getRate());
        }
        private Person getPersonBeanFromDB1(){
        Person pb = new PersonImpl();
        pb.setName("remy");
        pb.setGender("girl");
        pb.setRate(1);
        return pb;     }
        输出结果:
        Java代码
        remy     can not setRate     remy     2

        编辑特别推荐:

        Java读取文件内容再编辑

        JS获取单选与多选按纽的值

        每一种文件类型所对应的ContentType

  • 收藏 | 打印
  • 相关内容