zoukankan      html  css  js  c++  java
  • 代理模式

    一、什么是代理
    代理对象代替被代理对象干活


    二、代理作用
    对被代理对象方法的增强


    三、代理的种类:静态代理、动态代理
    3.1、静态代理
    3.1.1、定义抽象行为的类[抽象类、接口]
    3.1.2、定义具体类实现抽象行为
    3.1.3、定义代理类实现和具体类相同接口
    3.1.4、代理类中必须持有实现类对应的引用
    3.1.5、缺点:只能代理一类对象
    3.2、动态代理
    3.2.1、动态代理2种:JDK动态代理、cglib代理
    3.2.2、JDK动态代理:为实现接口的类动态创建代理类(即:帮你生成代理对象, 只能代理实现接口的类),然后调用回调方法。

    四、代码演示

    4.1静态代理

    package com.statics.proxy;
    
    /**
     * 接口
     */
    public interface IFunction {
        public String getBtnName();
        void click();
    }
    
    
    package com.statics.proxy;
    
    /**
     * 实体对象:按钮
     */
    public class Button implements IFunction {
    
        private String btnName;
    
        public String getBtnName(){
            return btnName;
        }
    
        public Button(String btnName){
            this.btnName = btnName;
        }
    
        @Override
        public void click() {
            System.out.println(this.btnName+"按钮被点击了");
        }
    }
    
    
    package com.statics.proxy;
    
    /**
     * 负责鉴权的代理类。即:在调用按钮前,检查是否有权限
     */
    public class ButtonProxy implements IFunction {
    
        //持有被代理对象的引用
        private IFunction function;
    
        //定义角色名称
        private String roleName;
    
        public ButtonProxy(IFunction function,String roleName){
             this.function = function;
             this.roleName = roleName;
        }
    
        @Override
        public String getBtnName() {
            return null;
        }
    
        @Override
        public void click() {
            if("admin".equals(roleName)){
                System.out.println("权限校验合法");
                function.click();
            }else{
                System.out.println("没有权限点击"+function.getBtnName());
            }
    
        }
    }
    
    
    package com.statics.proxy;
    
    /**
     * 静态代理测试类
     */
    public class TestStaticsProxy {
    
        public static void main(String[] args) {
            //创建提交按钮
            IFunction target = new Button("提交按钮");
            //没有代理之前的调用
            target.click();
            System.out.println("====================");
            //创建代理对象
            IFunction proxy = new ButtonProxy(target,"admin");
            //IFunction proxy = new ButtonProxy(target,"guest");
            //代理后点击调用方法
            proxy.click();
        }
    }
    

    4.2、动态代理

    4.2.1、JDK动态代理:创建代理对象,然后代理对象调用回调函数,最后完成代理对被代理对象增强

    package com.dynamic.proxy;
    
    public interface IFunction {
        void click();
        void dbClick();
        String getName();
    }
    
    
    package com.dynamic.proxy;
    
    public class Window implements IFunction {
    
        private String name;
    
        public Window(String name){
            this.name = name;
        }
    
        @Override
        public void click() {
            System.out.println(this.name+"被单击了");
        }
    
        @Override
        public void dbClick() {
            System.out.println(this.name+"被双击了");
        }
    
        @Override
        public String getName() {
            return name;
        }
        
    }
    
    package com.dynamic.proxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    /**
     * JDK动态代理:只能代理实现接口的类
    * 如果要加注解,需要在接口上面加注解,不在实现类上加。否则Method.isAnnotationPresent(Xxx.class)找不到 */ public class ObjectProxy { //持有目标代理类对象 private Object target; public ObjectProxy(){ } public ObjectProxy(Object target){ this.target = target; } /** * 定义生成目标对象代理对象的方法 * 生成代理对象 * Proxy.newProxyInstance第三个参数是回调,代理对象执行 */ public Object createProxy(){ return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),new Handle()); } /*** * 回调处理的内部类 */ private class Handle implements InvocationHandler{ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { validateLogin(); validateRole(); Object obj = method.invoke(target,args); requestData(); responseData(); return obj; } } private void validateLogin(){ System.out.println("验证登录,验证成功"); } private void validateRole(){ System.out.println("验证角色,验证成功"); } private void requestData(){ System.out.println("请求服务器端数据"); } private void responseData(){ System.out.println("返回服务器端数据"); } } package com.dynamic.proxy; public class TestDynamicProxy { public static void main(String[] args) { //创建目标代理对象 IFunction target = new Window("模态窗口"); target.click(); target.dbClick(); System.out.println("===================="); //创建一个代理对象 ObjectProxy op = new ObjectProxy(target); IFunction proxy = (IFunction) op.createProxy(); proxy.click(); System.out.println("===================="); proxy.dbClick(); } }

    5、cglib代理

    JDK代理要求被代理的类必须实现接口,有很强的局限性。而CGLIB动态代理则没有此类强制性要求。简单的说,CGLIB会让生成的代理类继承被代理类,并在代理类中对代理方法进行强化处理(前置处理、后置处理等)。在CGLIB底层,其实是借助了ASM这个非常强大的Java字节码生成框架。
    package com.cglib.proxy;
    
    /**
     * 被代理类
     */
    public class Button {
    
        public void click() {
            System.out.println("按钮被点击了");
        }
    
    }
    
    
    package com.cglib.proxy;
    
    import org.springframework.cglib.proxy.Enhancer;
    import org.springframework.cglib.proxy.MethodInterceptor;
    import org.springframework.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.Method;
    
    /**
     * MethodInterceptor拦截
     */
    public class ButtonMethodInterceptor implements MethodInterceptor {
    
        /**
         *
         * @param o              被代理对象
         * @param method        代理增加方法
         * @param objects       代理方法参数
         * @param methodProxy  代理方法
         * @return
         * @throws Throwable
         */
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            System.out.println("before:权限检查");
            Object object = methodProxy.invokeSuper(o,objects);
            System.out.println("after:权限检查通过");
            return object;
        }
    
    }
    
    
    package com.cglib.proxy;
    
    import org.springframework.cglib.proxy.Enhancer;
    
    /**
     * Cglib动态代理创建
     */
    public class ButtonProxy {
    
        public Object createCglibProxy(){
            Enhancer enhancer=new Enhancer();
            enhancer.setSuperclass(Button.class);
            enhancer.setCallback(new ButtonMethodInterceptor());
            Button proxy = (Button)enhancer.create();
            return proxy;
        }
    
        public static void main(String[] args) {
            Button buttonProxy = (Button)new ButtonProxy().createCglibProxy();
            buttonProxy.click();
        }
    }
  • 相关阅读:
    Canvas文本绘制
    Canvas贝塞尔三级曲线
    Canvas贝塞尔二级曲线
    Canvas arcTo绘制圆弧
    mybatis springmvc调用oracle存储过程,返回记录集
    java调用oracle存储过程,返回结果集
    oracle存储过程返回结果集
    存储过程变量类型定义与表字段一致
    HTML5获取当前的经纬度坐标
    实现精灵沿着圆形轨迹运动
  • 原文地址:https://www.cnblogs.com/chenweichu/p/8306740.html
Copyright © 2011-2022 走看看