Live2D

java基础——静态代理和动态代理

java代理模式有静态代理和动态代理两种实现方式

一、静态代理

代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强。代理类和被代理类应该共同实现一个接口,或者是共同继承某个类。

  优点:

    可以在不修改目标对象的前提下扩展目标对象的功能。
  缺点:
    冗余:由于代理对象要实现与目标对象一致的接口,会产生过多的代理类。
    不易维护:一旦接口增加方法,目标对象与代理对象都要进行修改。

 

  **静态代理的特点**

    1、目标角色固定

    2、在应用程序执行前就得到目标角色

    3、代理对象会增强目标对象的行为

    4、有可能存在多个代理 引起"类爆炸"(缺点)

 

二、动态代理

  动态代理利用了 JDK API,动态地在内存中构建代理对象,从而实现对目标对象的代理功能。

  动态代理又被称为 JDK 代理或接口代理。静态代理与动态代理的区别主要在:

    1、静态代理在编译时就已经实现,编译完成后代理类是一个实际的 class 文件
    2、动态代理是在运行时动态生成的,即编译完成后没有实际的 class 文件,而是在运行时动态生成类字节码,并加载到 JVM 中
  注意:动态代理对象不需要实现接口,但是要求目标对象必须实现接口,否则不能使用动态代理。

  JDK 中生成代理对象主要涉及两个类,第一个类为 java.lang.reflect.Proxy,通过静态方法 newProxyInstance 生成代理对象,第二个为 java.lang.reflect.InvocationHandler 接口,通过 invoke 方法对业务进行增强

  **动态代理的特点**

    1、目标对象不固定

    2、在应用程序执行时动态创建目标对象

    3、代理对象会增强目标对象的行为

三、代码实例

  1、创建一个person接口,这个接口就是租客和中介的公共接口,这个接口有一个rentHouse()方法。

public interface Person {

    //租房
    public void rentHouse();
}

 

  2、创建租客Renter类,实现上述接口

复制代码
public class Renter implements Person{

    @Override
    public void rentHouse() {
        System.out.println("租客租房成功!");
        
    }

}
复制代码

  3、静态代理

    1)创建中介类RenterProxy,同样实现Person接口,但是还另外持有一个租客类对象
复制代码
public class RenterProxy implements Person{
    private Person renter;
    public RenterProxy(Person renter){
        this.renter = renter;
    }
    @Override
    public void rentHouse() {
        System.out.println("中介找房东租房,转租给租客!");
        renter.rentHouse();
        System.out.println("中介给租客钥匙,租客入住!");
        
    }

}
复制代码

    2)测试

复制代码
public class StaticProxyTest {

    public static void main(String[] args) {
        Person renter = new Renter();
        RenterProxy proxy = new RenterProxy(renter);
        proxy.rentHouse();
    }

}

运行结果:
中介找房东租房,转租给租客!
租客租房成功!
中介给租客钥匙,租客入住!
复制代码

   4、动态代理

    1)创建RenterInvocationHandler类,这个类实现了InvocationHandler接口,并持有一个被代理类的对象,InvocationHandler中有一个invoke方法,所有执行代理对象的方法都会被替换成执行invoke方法。然后通过反射在invoke方法中执行代理类的方法。在代理过程中,在执行代理类的方法前或者后可以执行自己的操作,这就是spring aop的主要原理。

复制代码
public class RenterInvocationHandler<T> implements InvocationHandler{
    //被代理类的对象
    private T target;
    
    public RenterInvocationHandler(T target){
        this.target = target;
    }

    /**
     * proxy:代表动态代理对象
     * method:代表正在执行的方法
     * args:代表调用目标方法时传入的实参
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        //代理过程中插入其他操作
        System.out.println("租客和中介交流");
        Object result = method.invoke(target, args);
        return result;
    }

}
复制代码

    2)测试

复制代码
public class ProxyTest {

    public static void main(String[] args) {

        //创建被代理的实例对象
        Person renter = new Renter();
        //创建InvocationHandler对象
        InvocationHandler renterHandler = new RenterInvocationHandler<Person>(renter);
        
        
        //创建代理对象,代理对象的每个执行方法都会替换执行Invocation中的invoke方法
        Person renterProxy = (Person)Proxy.newProxyInstance(Person.class.getClassLoader(),new Class<?>[]{Person.class}, renterHandler);
        renterProxy.rentHouse();
        
        //也可以使用下面的方式创建代理类对象,Proxy.newProxyInstance其实就是对下面代码的封装
        /*try {
            //使用Proxy类的getProxyClass静态方法生成一个动态代理类renterProxy 
            Class<?> renterProxyClass = Proxy.getProxyClass(Person.class.getClassLoader(), new Class<?>[]{Person.class});
            //获取代理类renterProxy的构造器,参数为InvocationHandler
            Constructor<?> constructor = renterProxyClass.getConstructor(InvocationHandler.class);
            //使用构造器创建一个代理类实例对象
            Person renterProxy = (Person)constructor.newInstance(renterHandler);
            renterProxy.rentHouse();
            //
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }*/
    }

}

执行结果:
租客和中介交流
租客租房成功!
复制代码

 

 

 

参考:

https://blog.csdn.net/zjshuster/article/details/126439883

https://blog.csdn.net/qq_34609889/article/details/85317582

https://blog.csdn.net/longzorg_cn/article/details/129115728 

https://blog.csdn.net/m0_67499084/article/details/124810718 

一个person接口,这个接口就是租客和中介的公共接口,这个接口有一个rentHouse()方法
posted @   -涂涂-  阅读(692)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
历史上的今天:
2019-04-07 排序算法的各项比较以及各自的特点
点击右上角即可分享
微信分享提示