java中的proxy代理简单说明,以及静态代理和动态代理的简单代码示例

作者: admin 分类: JAVA 发布时间: 2019-06-21 13:19  阅读: 556 views

学习编写RPC逻辑示例代码的过程中,有用到java动态代理,所以这里简单整理下,方便日后查阅:

 

代理是一种模式,提供了对目标对象的间接访问方式,即通过代理访问目标对象。如此便于在目标实现的基础上增加额外的功能操作,前拦截,后拦截等,以满足自身的业务需求,同时代理模式便于扩展目标对象功能的特点。

动态代理特点:比较灵活,可以在运行的时候才切入改变类的方法,而不需要预先定义它。

场景: 权限控制、方法响应时间统计等。不需要改动具体的实现方法,而是通过代理在执行前后做处理。RPC、AOP就是应用了动态代理。

 

动态代理中有两个重要的方法:

1.实现InvocationHandler的invoke方法生成proxy实例
Object invoke(Object proxy, Method method, Object[] args) throws Throwable
三个参数的具体意思:
proxy:生成的代理类对象
method:被代理类的某个具体方法
arg0:实现方法的具体参数

2.动态生成代理类
public static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h) throws IllegalArgumentException
loader 类加载器,被代理对象的类加载器
interfaces 代理对象实现的接口
h  代理实例

 

代码示例 – 静态代理

package com.chl.proxy;

/**
 * 静态代理模式,简单示例
 * 代理模式优点:
    职责清晰 真实角色只需关注业务逻辑的实现,非业务逻辑部分,后期通过代理类完成即可。
    高扩展性 不管真实角色如何变化,由于接口是固定的,代理类无需做任何改动。
 * @author chenhailong
 *
 */
public class StaticProxyText {

    public static void main(String[] args) {
        employeeA a = new employeeA("小王");
        employeeB b = new employeeB(a);
        //b员工做代理,实际是a在做事情
        b.doSomething();
    }
}

/**
 * 通用员工行为
 */
interface Common {
    void doSomething();
}

/**
 * a员工
 */
class employeeA implements Common {

    private String name;

    employeeA(String name) {
        this.name = name;
    }

    @Override
    public void doSomething() {
        System.out.println("exec:" + name);
    }

}

/**
 * b员工
 */
class employeeB implements Common {

    private Common com;

    employeeB(Common com) {
        this.com = com;
    }

    @Override
    public void doSomething() {
        com.doSomething();
    }

}

代码示例 – 动态代理

package com.chl.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 动态代理实现
 * 通过实现InvocationHandler接口达到目的
 * 代理对象无需实现接口,免去了编写很多代理类的烦恼,同时接口增加方法也无需再维护目标对象和代理对象,只需在事件处理器中添加对方法的判断即可
 * @author chenhailong
 */
public class DynamicProxyText {

    public static void main(String[] args) {
        //被代理对象
        elephant el = new elephant();
        //中介类
        landAnimals la = new landAnimals(el);
        //类加载器
        ClassLoader loader = el.getClass().getClassLoader();
        //代理类一
        animals a = (animals)Proxy.newProxyInstance(loader, el.getClass().getInterfaces(), la);
        a.growUpTime();
        
        //代理类二
        animals b = vegetarianAnimals.getInstance(animals.class);
        b.growUpTime();
    }
}

/**
 * 通用动物操作
 */
interface animals{
    void growUpTime();
}

/**
 * 大象的成长
 */
class elephant implements animals{
    
    @Override
    public void growUpTime() {
        try {
            Thread.sleep(5 * 1000l);
            System.out.println("after 5 s,elephant is getting bigger !");
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

/**
 * 代理为陆地动物
 */
class landAnimals implements InvocationHandler{
    
    private animals als ;
    
    landAnimals(animals als){
        this.als = als;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before growup--!"+ System.currentTimeMillis());
        method.invoke(als, args);
        System.out.println("after  growup--!"+ System.currentTimeMillis());
        return null;
    }
}

/**
 * 素食动物
 */
class vegetarianAnimals{
    
    static InvocationHandler handler = new InvocationHandler() {
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //获取proxy的接口类
            System.out.println(proxy.getClass().getInterfaces()[0].getName());
            System.out.println("before eat--!"+ System.currentTimeMillis());
            method.invoke(new elephant(), args);
            System.out.println("after  eat--!"+ System.currentTimeMillis());
            return null;
        }
    };
    
    @SuppressWarnings("unchecked")
    static  T getInstance(Class cls) {
        return (T)Proxy.newProxyInstance(cls.getClassLoader(), new Class[]{cls}, handler);
    }
}

 

JDK动态代理是面向接口的。
CGLib动态代理是通过字节码底层继承要代理类来实现。
无需频繁的创建代理对象,比较适合采用CGLib动态代理,反之,则比较适用JDK动态代理。


   原创文章,转载请标明本文链接: java中的proxy代理简单说明,以及静态代理和动态代理的简单代码示例

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

发表评论

电子邮件地址不会被公开。 必填项已用*标注

更多阅读