玩命加载中 . . .

代理模式


代理模式

概念:代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,通过代理类,为原始类(⽬标)增加额外的功能

好处:利于原始类(⽬标)的维护

静态代理

概念:由程序员创建或特定工具自动生成源代码,也就是在编译时就已经将接口、代理类等确定下来

好处:实现简单 缺点:代码多,每一个目标内都需要重新写一个代理类

实现:

​ 1.创建一个接口

/**
 * 行为接口
 */
public interface Action {
    //吃东西
    void eat();
}

​ 2.创建一个实现类

/**
 * 行为接口实现类
 */
public class Person implements Action{
    @Override
    public void eat() {
        System.out.println("我要吃炒饭!");
    }
}

​ 3.创建目标类的代理类

class PersonProxy implements Action{

    private Person person = new Person();

    @Override
    public void eat() {
        //做饭的过程由代理类实现(额外功能)
        System.out.println("炒饭的过程~");
        //核心功能
        person.eat();
    }

    public static void main(String[] args) {

        new PersonProxy().eat();

    }

}

完整的代码

public class Person implements Action{
    @Override
    public void eat() {
        System.out.println("我要吃炒饭!");
    }
}
class PersonProxy implements Action{

    private Person person = new Person();

    @Override
    public void eat() {
        System.out.println("炒饭的过程~");
        person.eat();
    }

    public static void main(String[] args) {

        new PersonProxy().eat();

    }

}

动态代理

概念:动态代理,代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的“指示”动态生成的。相比于静态代理, 动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类中的方法

采用JDK代理实现:JDK动态代理实现InvocationHandler接口

class ProxyInvocationHandler implements InvocationHandler{
    //需要代理的实现对象
    private Object object;

    public ProxyInvocationHandler(Object object) {
        this.object = object;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //额外功能
        System.out.println("给猫主子抓鱼去~~");
        //创建原始对象
        Object invoke = method.invoke(object, args);
        //返回原始对象
        return invoke;
    }
}

​ 具体的实现类

/**
* Action接口的实现类
*/
public class Cat implements Action{
    @Override
    public void eat() {
        System.out.println("猫要吃鱼!");
    }

    public static void main(String[] args) {
        Cat cat = new Cat();
        //jdk动态代理创建,原始对象需要有接口的实现
        Action action = (Action) Proxy.newProxyInstance(Cat.class.getClassLoader(), Cat.class.getInterfaces(), new ProxyInvocationHandler(cat));
        action.eat();
    }

}

完整代码:

public class Cat implements Action{
    @Override
    public void eat() {
        System.out.println("猫要吃鱼!");
    }

    public static void main(String[] args) {
        Cat cat = new Cat();
        //jdk动态代理创建,需要有相同的接口
        Action action = (Action) Proxy.newProxyInstance(Cat.class.getClassLoader(), Cat.class.getInterfaces(), new ProxyInvocationHandler(cat));
        action.eat();
    }

}

class ProxyInvocationHandler implements InvocationHandler{
    //需要代理的实现对象
    private Object object;

    public ProxyInvocationHandler(Object object) {
        this.object = object;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //额外功能
        System.out.println("给猫主子抓鱼去~~");
        //原始对象
        Object invoke = method.invoke(object, args);
        return invoke;
    }
}

CGLIB代理实现:实现MethodInterceptor接口

public class Cat {

    public void eat(){
        System.out.println("本喵要吃饼干!");
    }

    public static void main(String[] args) {

        Enhancer enhancer = new Enhancer();
        //设置类加载器,谁的都行
        enhancer.setClassLoader(Cat.class.getClassLoader());
        //传入父类
        enhancer.setSuperclass(Cat.class);
        //原始对象的执行
        enhancer.setCallback(new CglibProxy(new Cat()));
        //创建代理对象
        Cat cat = (Cat) enhancer.create();
        cat.eat();
    }

}

/**
 * Cglib动态代理,实现MethodInterceptor接口
 */
class CglibProxy implements MethodInterceptor{
    //需要创建代理对象的原始对象
    private Object object;

    public CglibProxy(Object object) {
        this.object = object;
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("给猫主子买好了饼干~");
        //创建原始对象
        Object invoke = method.invoke(object, objects);
        //返回
        return invoke;
    }
}

​ cglib方式需要java,建议在maven项目中测试加入spring依赖

JDK和CGLIB动态代理总结

  • JDK动态代理只能对实现了接口的类生成代理,而不能针对类 ,使用的是 Java反射技术实现,生成类的过程比较高效。

  • CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法 ,使用asm字节码框架实现,相关执行的过程比较高效,生成类的过程可以利用缓存弥补,因为是继承,所以该类或方法最好不要声明成final 

  • JDK代理是不需要第三方库支持,只需要JDK环境就可以进行代理,使用条件:实现InvocationHandler + 使用Proxy.newProxyInstance产生代理对象 + 被代理的对象必须要实现接口

  • CGLib必须依赖于CGLib的类库,但是它需要类来实现任何接口代理的是指定的类生成一个子类,覆盖其中的方法,是一种继承但是针对接口编程的环境下推荐使用JDK的代理;


文章作者: 糖人
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 糖人 !
评论
  目录