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

    代理模式,为其他对象提供一种代理以控制对这个对象的访问。【大话设计模式】

    一张图,说明代理模式的结构。代理在客户端和目标对象起到的是中介的作用,一种桥梁,也如大话设计模式中所言,为他人做嫁衣。

    代理模式按照创建时期可以分为两类:静态代理、动态代理。

    静态代理

    首先介绍一下静态代理,静态代理的结构完全契合于上图,需要首先定义个接口,业务实现接口,然后定义代理类,且需要实现所有的相同的接口。

    首先,定义一个业务接口:

    public interface Account
    {
        public void save();
    }

    然后,定义代理类,实现业务接口

    public class AccountImpl implements Account
    {
        
        @Override
        public void save()
        {
            System.out.println("保存中。。。。。");
        }
        
    }

    接下来,实现代理类

    public class AccountProxy implements Account
    {
        private AccountImpl accountImpl;
        
        public AccountProxy(AccountImpl accountImpl)
        {
            this.accountImpl = accountImpl;
        }
        
        @Override
        public void save()
        {
            System.out.println("开始保存啦。。。。。");
            accountImpl.save();
            System.out.println("保存结束啦。。。。。");
        }
        
    }

    客户端类:

    public class TestAccount
    {
        public static void main(String[] args)
        {
            AccountImpl accountImpl = new AccountImpl();
            AccountProxy proxy = new AccountProxy(accountImpl);
            proxy.save();
        }
    }

     结果如下:

    开始保存啦。。。。。
    保存中。。。。。
    保存结束啦。。。。。

    这样静态的代理模式就可以完成了。但是,有个问题,就是代理类要实现所有的业务接口,这样就会造成很多代码重复,为了解决这些,需要用接下来的动态代理模式来实现。

    动态代理模式

    我们接着用上边的例子,通过动态代理模式实现代理。

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class DynamicProxy implements InvocationHandler
    {
        private Object target;
        
        public Object newInstance(Object target)
        {
            this.target = target;
            return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
        {
            Object result = null;
            System.out.println("begin");
            result = method.invoke(target, args);
            System.out.println("end");
            return result;
        }
    }

    客户端调用如下:

    import com.huawei.model.proxy.Account;
    import com.huawei.model.proxy.AccountImpl;
    
    public class TestProxy {    
        
        public static void main(String[] args) {    
            DynamicProxy proxy = new DynamicProxy();    
            //在这里进行真正的对象传入  
            Account account= (Account )proxy.newInstance(new AccountImpl());    
            account.save();  
        } 
    }

    通过对比,我们可以发现,通过动态代理,我们省略了关于代理接口的实现方法,不用讲所有需要被代理的全部方法都要实现,即可实现代理功能。

    通过以上方法实现,我们仍然是需要接口的,如果没有接口,该怎么办?

    CGLib动态代理

    CGLib是一个类库,它可以在运行期间动态生成字节码,动态生成代理类。

    代码如下:

    import java.lang.reflect.Method;
    
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    public class CglibProxy implements MethodInterceptor
    {
    
        public <T> T getProxy(Class<T> cls)
        {
            return (T)Enhancer.create(cls, this);
        }
        
        @Override
        public Object intercept(Object obj, Method method, Object[] arg2, MethodProxy proxy) throws Throwable
        {
            System.out.println("开始保存啦。。。。。");
            Object result = proxy.invokeSuper(obj, arg2);
            System.out.println("保存结束啦。。。。。");
            return result;
        }
        
    }

    客户端调用代码:

    import com.huawei.model.proxy.Account;
    import com.huawei.model.proxy.AccountImpl;
    
    public class TestProxy
    {
        public static void main(String[] args)
        {
            CglibProxy proxy = new CglibProxy();
            Account account = proxy.getProxy(AccountImpl.class);
            account.save();
        }
    }

    输出结果:

    开始保存啦。。。。。
    保存中。。。。。
    保存结束啦。。。。。

    虽然该方法比上述两种方式均更加灵活,但是其也有自己的缺点,就是会拦截被代理类的所有方法。

    参考链接:

    https://www.zhihu.com/question/20794107

    http://blog.csdn.net/wangyongxia921/article/details/46240877

  • 相关阅读:
    Python、PyCharm的安装及使用方法(Mac版)
    学习Java web技术
    Java Web基础教程
    JavaWeb--深入Servlet与JSP(运行原理)
    Servlet入门总结及第一个Servlet程序
    Mac系统安装和配置tomcat步骤详解
    Struts2进阶学习4
    Struts2进阶学习3
    Struts2基础学习2
    Struts2基础入门
  • 原文地址:https://www.cnblogs.com/woniu4/p/8360761.html
Copyright © 2011-2022 走看看