JAVA代理,静态代理,动态代理JDK接口代理、Cglib代理

 

代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.
这里使用到编程中的一个思想:不要随意去修改别人已经写好的代码或者方法,如果需改修改,可以通过代理的方式来扩展该方法

举个例子来说明代理的作用:比如说我们要吃午餐,在没有点餐平台前,只能去饭店吃;后来有了美团外卖,我们还是吃同一家饭店的午餐,却不用直接去饭店才能吃午餐了,直接在美团上点餐,就可以吃到香喷喷的午餐了,美团就相当于代理了饭店,提供送餐功能。

我们javaWEB开发常用的spring、mybatis等框架底层都是用了动态代理,接下来将用三个demo来分析三种代理模式的优缺点。

一、静态代理。

接口:hello.java

public interface Hello {
    void sayHello(String string);
    void sayHi(String string);
}

 实现类:ImpHello

public class ImpHello implements Hello{
    @Override
    public void sayHello(String string) {
        System.out.println("我说:"+string);
    }

    @Override
    public void sayHi(String string){
        System.out.println("sayHi:"+string);
    }
}

 我们需要在执行实现类sayHello前打印一下say的内容,就有下下代理对象:

public class StaticProxiedHello implements Hello{
    private ImpHello impHello=new ImpHello();


    @Override
    public void sayHello(String string) {
        System.out.println("你说:"+string);
        impHello.sayHello(string);
    }

    @Override
    public void sayHi(String string) {
        System.out.println(string);
    }

 

@Test
    public void testProxi() {
        //======================静态代理
        StaticProxiedHello staticProxiedHello=new StaticProxiedHello();
        staticProxiedHello.sayHello("很爱很爱你");
}

控制台打印:

你说:很爱很爱你
我说:很爱很爱你

可见静态代理

1.可以做到在不修改目标对象的功能前提下,对目标功能扩展.
2.缺点:

  • 因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多.同时,一旦接口增加方法,目标对象与代理对象都要维护.

二、JDK接口动态代理

 

代理对象代码如下,JDK动态代理对象必须实现InvocationHandler接口

public class ProxyHello implements InvocationHandler {

    private Hello hello;

    public ProxyHello(Hello hello){
        this.hello=hello;
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.out.println("进入代理方法=========================");
        if("sayHello".equals(method.getName())){
            System.out.println("你说:"+Arrays.toString(args));
        }

        if("sayHi".equals(method.getName())){
            System.out.println("你说:"+Arrays.toString(args));
        }

        // System.out.println("你说:"+Arrays.toString(args));
        return method.invoke(hello,args);
    }
}

2.测试JDK代理代码如下

 @Test
    public void testJDKProxie() {

        // 0. 在需要使用Hello的时候,通过JDK动态代理获取Hello的代理对象。
        Hello hello = (Hello)Proxy.newProxyInstance(
                getClass().getClassLoader(), // 1. 类加载器
                new Class<?>[] {Hello.class}, // 2. 代理需要实现的接口,可以有多个
                new ProxyHello(new ImpHello()));// 3. 方法调用的实际处理者
        hello.sayHello("你好啊");
        System.out.println(hello.getClass().getName());

 执行结果:

你说:[你好啊]
我说:你好啊
com.sun.proxy.$Proxy4

注意打印JDK动态代理生成的类名为$Proxy4

可见JDK动态代理:

  1.代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能用动态代理;

  2.代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型)
  3.动态代理也叫做:JDK代理,接口代理

三、cglib动态代理

1.cglib代理对象

public class CglibInterceptor implements MethodInterceptor {

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("CGLIB动态代理"+ Arrays.toString(objects));
        return methodProxy.invokeSuper(o,objects);
    }
}

2.测试类

 @Test
    public void testCGLIB() {


        //================cglib动态代理

        Enhancer enhancer=new Enhancer();
        enhancer.setSuperclass(ImpHello.class);
        enhancer.setCallback(new CglibInterceptor());
        Hello hello=(Hello) enhancer.create();
        hello1.sayHello("I love you!!!!!!");
       System.out.println(hello.getClass().getName());


    }

打印结果

CGLIB动态代理[I love you!!!!!!]
我说:I love you!!!!!!
yuan.base.yuanjpa.ImpHello$$EnhancerByCGLIB$$857ffca1

 

可见CGLIB代理:

1.对比其他代理不需要实现接口。

spring aop就用到了JDK、和cglib代理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值