• 代理设计模式


    1、反射

    通过反射加载类的构造器并新建对象

    package ref;
    
    import java.lang.reflect.InvocationTargetException;
    
    public class ReflectServiceImpl {
        private String name;
    
        public void sayHello(){
            System.out.println("hello "+name);
        }
    
        public ReflectServiceImpl(String  name) {
            this.name = name;
        }
    
        public static void main(String[] args) {
            ReflectServiceImpl object = null;
            try {
                object = (ReflectServiceImpl) Class.forName("ref.ReflectServiceImpl").getConstructor(String.class).newInstance("aa");
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
    
            System.out.println(object.getClass().getName());
            object.sayHello();
        }
    }

    通过反射执行方法,这种执行是在先使用new关键字创建了对象的情况下,也可以使用反射创建对象然后反射执行方法

            ReflectServiceImpl target = new ReflectServiceImpl();
            Method method = ReflectServiceImpl.class.getMethod("sayHello", String.class);
            method.invoke(target,"张三"); 

    其实就是把上面的两种结合起来

           ReflectServiceImpl target = (ReflectServiceImpl)Class.forName("ref.ReflectServiceImpl").newInstance();
            Method method = ReflectServiceImpl.class.getMethod("sayHello", String.class);
            method.invoke(target,"张三");

    2、动态代理

      所谓代理模式就是在不改变方法源码的情况下对原方法进行增强,允许用户在运行期间创建基于接口的代理去增强接口代码。该技术涉及到反射中的两个类:Proxy InvocationHandler。实现invocationHandler接口的类负责把接口的逻辑和要增强的逻辑组装起来,Proxy通过新建代理对象的方式来执行InvocationHandler的组合逻辑。

      实现动态代理首先要有一个接口,以及该接口的一个实现类作为被代理的对象。

    package daili;
    
    public class Actor_01 implements Actor {
    
        @Override
        public void act(float money) {
            System.out.println("开始普通表演 拿到:"+money);
        }
    
        @Override
        public void dangerAct(float money) {
            System.out.println("开始危险表演 拿到:"+money);
    
        }
    }
    package daili;
    
    public interface Actor {
        void act(float money);
        void dangerAct(float money);
    }

      然后实现InvocationHandler接口的类作为代理对象,代理对象调用被代理的对象的相关方法,以及织入横切逻辑。所以代理对象里一定要有被代理对象的引用,实现这种引用既可以通过属性的方式来实现,也可以用个匿名内部类调用外部类属性来实现,但是后者要求该属性必须是final,这或多或少有一点侵入的意思,所以这里采用了直接实现InnovationHandler方式。

      invoke方法中,调用method.invoke是执行被代理的对象的方法,而在method.invoke前后就是可以随意织入的方法。

    public class ActorHandler implements InvocationHandler {
        private Actor actor;
    
        public void setActor(Actor actor) {
            this.actor = actor;
        }
    
        public ActorHandler(Actor actor) {
            this.actor = actor;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("我是代理公司");
            float money= (float)args[0];
            Object result = null;
            if (money>100){
                System.out.println("演员可以演");
                result = method.invoke(actor, args);
            }else {
                System.out.println("钱太少 我不让我的演员演");
            }
            return result;
        }
    }

      最后一步是调用Proxy的static方法newProxyInstance来调用增强后的方法。

    public class Client {
        public static void main(String[] args) {
            Actor_01 actor_01 = new Actor_01();
            Actor proxyInstance = (Actor)Proxy.newProxyInstance(actor_01.getClass().getClassLoader(), actor_01.getClass().getInterfaces(), new ActorHandler(actor_01));
            proxyInstance.act(100f);
            proxyInstance.act(500f);
        }
    }

  • 相关阅读:
    Mysql主外键
    行列转换
    简单的增删改查
    day22 面向对象基础
    day21 xml模块 ATM+购物车
    python学习 day19 configparser模块 os模块 subprocess模块
    day18 logging模块 sys shelve
    day17 正则表达式 re模块和hashlib模块
    day16 包的使用 json time 常用模块
    day15模块内容
  • 原文地址:https://www.cnblogs.com/AshOfTime/p/10600646.html
Copyright © 2020-2023  润新知