zoukankan      html  css  js  c++  java
  • 结构型之代理模式

    序言

      代理模式可以实现对被代理对象的间接控制,可以对被代理对象的方法进行增强,她不重写原有的方法。
    代理模式基本分为3类:

    1. jdk静态代理: 1个代理类只能代理1个类,局限性较大。
    2. jdk动态代理: 1个代理类能代理多个类,要求被代理类必须要有接口,利用了反射,效率比较低。
    3. cglib动态代理:1个代理类能代理多个类,被代理类不需要有接口,效率较高,不能代理final的类和方法

    1. jdk静态代理模式

    套路:

    1. 代理类要实现被代理类的接口,使代理类的方法与被代理类的保持一致。
    2. 代理类要加入一个被代理类的委托对象,由客户端初始化。
    3. 添加私有的增强方法。
    /**
     * 登录接口
     */
    public interface LoginService {
        public void login();
    }
    
    /**
     * 登录接口代理对象
     */
    public class LoginServiceProxy implements LoginService{
        private LoginService loginService;
    
        public LoginServiceProxy(LoginService loginService){
            this.loginService = loginService;
        }
        public void login() {
            preLogin();
            loginService.login();
            postLogin();
        }
        private void preLogin(){
            System.out.println("=====登录前认证校验=====");
        }
        private void postLogin(){
            System.out.println("=====登录后日志记录=====");
        }
    
    }
    
    /**
     * 登录接口实现类
     */
    public class LoginServiceImpl implements LoginService{
        public void login() {
            System.out.println("正在登录...");
        }
    }
    
    /**
     * jdk静态代理测试
     */
    public class JdkStaticProxyTest {
    
        @Test
        public void testJdkStaticProxy(){
            LoginServiceProxy loginServiceProxy = new LoginServiceProxy(new LoginServiceImpl());
            loginServiceProxy.login();
        }
    }
    

    2. jdk动态代理模式

    /**
     * 登录接口
     */
    public interface LoginService {
        public void login();
    }
    
    /**
     * 登录接口实现类
     */
    public class LoginServiceImpl implements LoginService {
        public void login() {
            System.out.println("正在登录...");
        }
    }
    
    /**
     * 登录接口代理对象
     */
    public class ServiceInvocationHandler implements InvocationHandler {
    
        //被代理对象
        private Object target;
    
        public ServiceInvocationHandler(Object object){
            this.target = object;
        }
    
        private void preOperation(){
            System.out.println("=====执行前校验=====");
        }
        private void postOperation(){
            System.out.println("=====执行后记录日志=====");
        }
    
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            preOperation();
            Object result = method.invoke(target, args);
            postOperation();
            return result;
        }
    
        public Object getProxy() throws Throwable {
    
            return Proxy.newProxyInstance(Thread.currentThread()
                    .getContextClassLoader(), this.target.getClass()
                    .getInterfaces(), this);
        }
    }
    
    /**
     * jdk静态代理测试
     */
    public class JdkDynamicProxyTest {
    
        @Test
        public void testJdkStaticProxy() throws Throwable {
            LoginService proxy = (LoginService) new ServiceInvocationHandler(new LoginServiceImpl()).getProxy();
            proxy.login();
            System.out.println(proxy.getClass());
        }
    }
    

    3. cglib动态代理模式

    /**
     * 登录类
     */
    public class LoginServiceImpl{
        public void login() {
            System.out.println("正在登录...");
        }
    }
    
    /**
     * 登录接口代理对象
     */
    public class LoginServiceProxy implements MethodInterceptor{
    
        private Object target;
    
        public LoginServiceProxy(Object obj){
            this.target = obj;
        }
    
        public Object getInstance(){
    
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(this.target.getClass());
            enhancer.setCallback(this); //设置回调方法
            return enhancer.create(); //创建代理对象
        }
    
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            preOpteration();
            Object result = methodProxy.invokeSuper(o, objects);
            postOpteration();
            return result;
        }
    
        private void preOpteration(){
            System.out.println("=====执行前校验=====");
        }
        private void postOpteration(){
            System.out.println("=====执行后记录日志=====");
        }
    
    }
    
    /**
     * cglib动态代理测试
     */
    public class CglibProxyTest {
        
        @Test
        public void testCglibProxy(){
            LoginServiceImpl loginServiceProxy = (LoginServiceImpl) new LoginServiceProxy(new LoginServiceImpl()).getInstance();
            loginServiceProxy.login();
        }
    }
    
    

    后记

  • 相关阅读:
    【Delphi】VCL 使用TCoolBar控件,在系统触发UAC界面时,引发CMSysFontChanged事件导致界面卡死或弹出System Error 1400错误
    【Delphi】 FMX 下 TImageList的使用方法:获取其中一张图片
    如何在电脑睡眠状态下保持程序运行
    【Delphi】使用TIdHTTPServer开发HTTP服务端在Windows2008部署后,外网无法访问
    fedora 25 virtualbox 增强功能安装
    在Win8系统中如何将一般类型的文件放在开始菜单中
    mac上的替代软件
    spring boot 1.4.1 with jsp file sample
    macbook pro 重装系统
    找不到或无法加载主类 org.codehaus.plexus.classworlds.launcher.Launcher
  • 原文地址:https://www.cnblogs.com/codebug/p/7339899.html
Copyright © 2011-2022 走看看