代理模式

代理模式

通过代理对象访问目标对象,在不改变目标对象的情况下,对目标对象进行方法增强.

代理主要分以下三种情况:

  • 静态代理
  • JDK动态代理
  • 使用cglib库实现动态代理

静态代理

1.定义一个接口

2.实现类

3.代理类

代码

1.定义接口

/**
 * 售票窗口
 */
public interface ITicketOffice {
    /**
     * 出售火车票
     * @param num  出售数量
     */
    void saleTicket(int num);
}

2.实现类

/**
 * 售票厅
 */
public class TicketOffice implements ITicketOffice{
    @Override
    public void saleTicket(int num) {
           System.out.println("出售车票数 :"+num);
    }
}

3.代理类

/**
 * 代售点
 */
public class ProxyTicketOffice implements ITicketOffice {
    /**
     * 售票厅对象
     */
    private TicketOffice ticketOffice;

    public ProxyTicketOffice(TicketOffice ticketOffice) {
        this.ticketOffice = ticketOffice;
    }

    @Override
    public void saleTicket(int num) {
        System.out.println("进入代售点");
        ticketOffice.saleTicket(num);
        System.out.println("离开代售点");
    }
}

4.测试

    @Test
    public void test(){
        ProxyTicketOffice proxyTicketOffice = new ProxyTicketOffice(new TicketOffice());
        proxyTicketOffice.saleTicket(2);

        //测试结果
        //进入代售点
        // 出售车票数 :2
        // 离开代售点
    }

JDK动态代理

Proxy类创建代理对象的方法

    /**
     * Proxy类中,创建代理对象的方法
     *
     * @param loader     类加载器,可以通过对象直接获取
     * @param interfaces 代理类需实现的接口的列表
     * @param h          调用处理器,InvocationHandler接口
     * @return          调用方法的返回值
     * @throws IllegalArgumentException
     */
    public static Object newProxyInstance(
    ClassLoader loader,
    Class<?>[] interfaces,
    InvocationHandler h)
            throws IllegalArgumentException {
          return null;
    }

1.定义一个接口

2.实现类

3.使用JDK中Proxy类,动态生成代理对象

代码

1.定义接口

/**
 * 售票窗口
 */
public interface ITicketOffice {
    /**
     * 出售火车票
     * @param num  出售数量
     */
    void saleTicket(int num);
}

2.实现类

/**
 * 售票厅
 */
public class TicketOffice implements ITicketOffice{
    @Override
    public void saleTicket(int num) {
           System.out.println("出售车票数 :"+num);
    }
}

3.测试

    @Test
    public void jdkProxyTest() {
        //1.创建目标对象
        ITicketOffice ticketOffice = new TicketOffice();
        //2.创建代理对象
        ITicketOffice proxyInstance = (ITicketOffice) Proxy.newProxyInstance(ticketOffice.getClass().getClassLoader(),
                ticketOffice.getClass().getInterfaces(),
                (proxy, method, args) -> {
                    System.out.println("进入代售点");
                    //使用反射的方式调用ticketOffice中的方法
                    Object invoke = method.invoke(ticketOffice, args);
                    System.out.println("离开代售点");
                    return invoke;
                }
        );
        proxyInstance.saleTicket(1);
        //测试结果
        //进入代售点
        // 出售车票数 :1
        // 离开代售点
    }

使用cglib库实现动态代理

1.导入cglib库

2.编写目标类(需要被代理的类)

3.使用cglib库中Enhancer类生成代理对象

代码

1.导入cglib库

        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>2.2.2</version>
        </dependency>

2.目标类

/**
 * 售票厅
 */
public class NewTicketOffice {
    
    public void saleTicket(int num) {
        System.out.println("出售车票数 :" + num);
    }
}

3.测试

    @Test
    public void cjlibProxyTest() {
        //1.创建目标对象
        ITicketOffice ticketOffice = new TicketOffice();
        //2.创建代理对象
        ITicketOffice proxyInstance = (ITicketOffice) Enhancer.create(ticketOffice.getClass(), new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                System.out.println("进入代售点");
                //使用反射的方式调用ticketOffice中的方法
                Object invoke = method.invoke(ticketOffice, objects);
                System.out.println("离开代售点");
                return invoke;
            }
        });
        proxyInstance.saleTicket(1);
        //测试结果
        //进入代售点
        // 出售车票数 :1
        // 离开代售点
    }

总结

1.代理分为静态代理和动态代理,动态代理又分为JDK动态代理和cjlib动态代理

2.静态代理实现了目标对象的所有方法,一旦目标接口增加方法,代理对象和目标对象都要进行相应的修改,增加维护成本。

3.使用JDK动态代理时,目标类最少实现一个接口,使用Proxy类在内存中动态构建代理对象

4.使用cjlib动态代理时,是基于子类的动态代理,目标类不需要实现接口,但是目标类不能被final关键字修饰.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值