Java-代理

来源:互联网 发布:聊天软件遇见 编辑:程序博客网 时间:2024/05/19 13:21

一、代理测试类:


大家一看就懂动态代理的作用了。

package com.che.baseutil.proxy;import org.junit.Before;import org.junit.Test;public class ProxyTestClient {    private UserImpl target;//被代理类    @Before    public void setUp() {        target = new UserImpl();    }    /**     * 原始     */    @Test    public void testTarget() {        target.login();        target.updateInfo();    }    /**     * 静态代理     */    @Test    public void testStaticProxy() {        UserStaticProxy staticProxy = new UserStaticProxy(target);        staticProxy.login();        staticProxy.updateInfo();    }    /**     * Jdk动态代理     */    @Test    public void testJdkProxy() {        JdkProxyFactory jdkFactory = new JdkProxyFactory();        IUser jdkProxy = (IUser) jdkFactory.createProxy(target);        jdkProxy.login();        jdkProxy.updateInfo();    }    /**     * Cglib动态代理     * <p>     * Jdk只能对接口进行代理,而cglib却可以对普通类进行代理!     * <p>     * 注意:此代码在Java环境可运行,但在Android环境会报错!     * 原因:Java是JVM虚拟器,Android是DarvikVM虚拟机,类加载机制有区别,而Cglib是基于继承的字节码生成技术,所有有问题。     * Android中推荐使用AspectJ,不过这个玩意在AS中的配置有点麻烦     */    @Test    public void testCglibProxy() {        CglibProxyFactory cglibFactory = new CglibProxyFactory();        IUser cglibProxy = (IUser) cglibFactory.createProxy(target);        cglibProxy.login();        cglibProxy.updateInfo();    }}

原始方式:

小明在登录……
小明在更新信息……

代理方式:

前置动作……
小明在登录……

前置动作……
小明在更新信息……
后置动作……

看,使用代理后,我可以在登录和更新命令时,自动添加一些前置动作(比如检查下网络什么的),而在原命令完成之后,我还可以自动添加一些后置操作(比如更新后保存到数据库中)

这样一来的话,在一样常见的场景中:例如日志统计、用户行为统计等,我们就再也不必在原方法前和原方法后加一坨重复的代码了!这其实就是AOP的编程思想!大家不妨自己谷歌下。

二、代理实现:

其实静态代理和Cglib的动态代理都不一定需要接口,不过Jdk的代理的话,就必须要实现接口了。
1.接口

/** * 用户接口 * <p> * 作者:余天然 on 16/9/18 下午3:45 */public interface IUser {    void login();    void updateInfo();}

2.实现类

/** * 用户接口实现类 * <p> * 作者:余天然 on 16/9/18 下午3:45 */public class UserImpl implements IUser {    @Override    public void login() {        System.out.println("小明在登录……");    }    @Override    public void updateInfo() {        System.out.println("小明在更新信息……");    }}

3.静态代理类

package com.che.baseutil.proxy;/** * 静态代理类 * <p> * 作者:余天然 on 16/9/18 下午3:46 */public class UserStaticProxy implements IUser {    private UserImpl userImpl;    public UserStaticProxy(UserImpl userImpl) {        this.userImpl = userImpl;    }    /**     * 登录有前置动作     */    @Override    public void login() {        doBefore();        this.userImpl.login();    }    /**     * 更新有前置动作和后置动作     */    @Override    public void updateInfo() {        doBefore();        this.userImpl.updateInfo();        doAfter();    }    private void doBefore() {        System.out.println("静态代理:前置动作……");    }    private void doAfter() {        System.out.println("静态代理:后置动作……");    }}

4.JDK动态代理工厂

package com.che.baseutil.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;/** * Jdk动态代理 * <p> * 作者:余天然 on 16/9/18 下午3:47 */public class JdkProxyFactory implements InvocationHandler {    private Object target;    //创建代理类    public Object createProxy(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;        if (method.getName().equals("login")) {            doBefore();            result = method.invoke(target, args);        }        if (method.getName().equals("updateInfo")) {            doBefore();            result = method.invoke(target, args);            doAfter();        }        return result;    }    private void doBefore() {        System.out.println("JDK动态代理:前置动作……");    }    private void doAfter() {        System.out.println("JDK动态代理:后置动作……");    }}

5.Gglib动态代理工厂

package com.che.baseutil.proxy;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;/** * Cglib动态代理 * <p> * 作者:余天然 on 16/9/18 下午3:48 */public class CglibProxyFactory implements MethodInterceptor {    private Object target;    //创建代理类    public Object createProxy(Object target) {        this.target = target;        Enhancer enhancer = new Enhancer();        enhancer.setSuperclass(this.target.getClass());        enhancer.setCallback(this);        return enhancer.create();    }    //改变委托类方法的调用逻辑    @Override    public Object intercept(Object target, Method method, Object[] args, MethodProxy proxy) throws Throwable {        Object result = null;        if (method.getName().equals("login")) {            doBefore();            result = proxy.invokeSuper(target, args);        }        if (method.getName().equals("updateInfo")) {            doBefore();            result = proxy.invokeSuper(target, args);            doAfter();        }        return result;    }    private void doBefore() {        System.out.println("Cglib动态代理:前置动作……");    }    private void doAfter() {        System.out.println("Cglib动态代理:后置动作……");    }}


文/天然鱼(简书作者)
原文链接:http://www.jianshu.com/p/301446de9918
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 1岁宝宝感冒鼻塞怎么办 4个月宝宝鼻塞怎么办 4岁宝宝感冒鼻塞怎么办 宝宝4个月流鼻涕怎么办 3个月的宝宝鼻塞怎么办 50天的小孩鼻塞怎么办 鼻子流脓鼻涕2周怎么办 两岁宝宝流清鼻涕怎么办 1岁宝宝流黄鼻涕怎么办 宝宝上火流黄鼻涕怎么办 一周岁宝宝流清鼻涕怎么办 一周岁流清鼻涕怎么办 4岁宝宝感冒发烧怎么办 6个月宝宝流鼻涕怎么办 8岁儿童感冒发烧怎么办 婴儿感冒咳嗽怎么办%3f 小孩流鼻涕鼻塞怎么办最简单方法 宝宝鼻炎鼻子不通气怎么办 小孩晚上睡觉鼻子不通气怎么办 孩子晚上睡觉鼻子不通气怎么办 3个月婴儿流鼻涕怎么办 一个月宝宝鼻塞流鼻涕怎么办 我的鼻子不通气怎么办 鼻子擦多了疼怎么办 鼻涕擦多了好疼怎么办 鼻炎一直流鼻水怎么办 擤鼻涕后耳朵堵怎么办 鼻涕醒多了头疼怎么办 感冒鼻子破皮了怎么办 感冒鼻子擦红了怎么办 擤鼻涕时耳朵疼怎么办 鼻涕进耳朵里了怎么办 怀孕6个月生病了怎么办 浓鼻涕擤不出来怎么办 有鼻涕在鼻腔里怎么办 感冒鼻子擤的疼怎么办 擤鼻涕耳膜破了怎么办 钢铁雄心4闪退怎么办 钢铁雄心4太卡怎么办 无主之地2卡怎么办 卡盟给骗了怎么办