Java 代理

1.什么是代理

代理模式是常用的Java设计模式,他们的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。简单的来说就是,我们在访问实际对象时,是通过代理对象来访问的。

简单来说,代理可以在不修改原目标类代码的前提下,增加或修改原目标类。同时避免了用户直接访问核心方法。

Java中的代理分为两大类:静态代理(基于jdk实现的静态代理)和动态代理(基于jdk实现的动态代理、基于CGLB实现的动态代理)。

2.静态代理

静态代理是指在程序运行前就已经存在代理类的字节码文件,代理类和目标类的关系在运行前就已确定,且代理类通常是手工编写的。

        其模式为由核心类(目标类)生成核心对象(目标对象),由代理类生成代理对象,在由代理对象代理核心对象,而核心类和代理类都会实现同一个接口。

        接口起到了一个沟通(通知)的作用,即通知代理类所要代理的核心是什么。

静态代理的案例:

1、接口类(BuyShoes)

接口核心方法clothes

package 代理;

public interface BuyClothes {

    void clothes(String size);

}
2、核心类(ShoesFactory) 

核心类实现核心方法

package 代理;
public class ClothesFactory implements BuyClothes{

    public void clothes(String size){
        System.out.println("为您定制了一款大小为"+size+"的衣服");
    }

}
3、代理类(Proxy)

创建目标类ClothesFactory的对象,实现接口的核心方法,在方法中调用核心类对象的核心方法。然后添加服务方法。

package 代理;
public class Proxy implements BuyClothes{

    private ClothesFactory clothesFactory = new ClothesFactory();

    @Override
    public void clothes(String size) {
        PreService();
        clothesFactory.clothes(size);
        AfterService();
    }

    public void PreService(){
        System.out.println("为您进行了市场调研");
    }

    public void AfterService(){
        System.out.println("为您提供一系列售后服务");
    }


}
 4、测试类
package 代理;
public class Test {
    public static void main(String[] args) {
        //静态代理
        Proxy proxy = new Proxy();
        proxy.clothes("2xl");
    }
}
 结果:

静态代理的缺点:

  1. 静态代理类和被代理类实现相同的接口,导致接口的数量增加,系统更加臃肿。

  2. 每一个代理类只能代理一个接口,如果要代理多个接口就需要创建多个代理类。

  3. 代理类需要手动编写,代码量较大,且容易出错。

3.动态代理

为了解决静态代理的问题,我们使用动态代理。动态代理可以通过Java的反射机制运行时动态地生成代理类,无需手动编写代理类。动态代理可以代理多个接口,且可以实现通用的代理逻辑,避免了代码重复,同时也避免了静态代理中需要手动编写代理类的缺点。

Java提供了java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口来实现动态代理。

动态代理的案例

1、接口类(BuyClothes)(BuyShoes)

接口类定义核心方法

public interface BuyClothes {
    void clothes(String size);
}
public interface BuyShoes {
    void shoes(String size);
}
2、核心类(ClothesFactory)(ShoesFactory)

核心类实现接口类的核心方法

public class ClothesFactory implements BuyClothes{
    public void clothes(String size){
        System.out.println("为您定制了一款大小为"+size+"的衣服");
    }
}
public class ShoesFactory implements BuyShoes{
    @Override
    public void shoes(String size) {
        System.out.println("为您定制了一款大小为"+size+"的鞋子");
    }
}
3、动态代理类(DyProxy)

定义一个实现了InvocationHandler接口的代理类,这个类中需要实现invoke方法,在该方法中实现对目标对象方法的调用和增强逻辑的织入

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

public class DyProxy implements InvocationHandler {
    //让用户告诉我们,要代理谁
    private Object o;
    public DyProxy(Object o){
        this.o = o;
    }

    //第二步:获取目标类的接口,要知道自己代理的核心方法是什么
    public Object getProxyInterface(){
        return Proxy.newProxyInstance(o.getClass().getClassLoader(), o.getClass().getInterfaces(),this);
    }

    //invoke方法是利用反射获取到要代理的核心方法
    //Object:jdk创建的代理类,无需赋值
    //Method:目标类当中的方法,jdk提供,无需赋值
    //Object[]:目标类当中的方法的参数,jdk提供,无需赋值
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        PreService();
        method.invoke(o,args);
        AfterService();
        return null;
    }

    public void PreService(){
        System.out.println("为您进行了市场调研");
    }

    public void AfterService(){
        System.out.println("为您提供一系列售后服务");
    }
}
4、Test类
public class Test {
    public static void main(String[] args) {
        //动态代理
        ClothesFactory clothesFactory = new ClothesFactory();
        DyProxy dyProxy1 = new DyProxy(clothesFactor);
        //已经知道了目标类当中的核心方法是什么
        BuyClothes clothes = (BuyClothes) dyProxy1.getProxyInterface();
        clothes.clothes("XXL");

        ShoesFactory shoesFactory = new ShoesFactory();
        DyProxy dyProxy2 = new DyProxy(shoesFactory);
        //已经知道了目标类当中的核心方法是什么
        BuyShoes shoes = (BuyShoes) dyProxy2.getProxyInterface();
        shoes.shoes("40");
    }
}
结果: 

相比静态代理,动态代理有以下优点

  1. 可以动态代理多个接口:动态代理使用的是接口代理,而不是类代理,因此可以代理多个接口。这对于需要实现多个接口的类来说非常方便。
  2. 避免了静态代理中需要手动编写代理类的缺点:动态代理是在运行时生成代理类的技术,可以避免静态代理中需要手动编写代理类的缺点。
  3. 代码更简洁:由于动态代理可以实现通用的代理逻辑,因此代码更加简洁。
  4. 可以支持 AOP 编程:动态代理可以实现 AOP 编程,即在不修改原有代码的情况下,增加日志、事务等功能。

总之,动态代理相比静态代理更加灵活、方便、简洁,可以避免代码重复,实现通用的代理逻辑,支持 AOP 编程。因此,在实际开发中,我们应该尽量使用动态代理,避免使用静态代理。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值