代理模式【设计模式-结构型模式】

概述

  由于某些原因需要给某对象提供一个代理以控制该对象的访问。这时访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。

  Java中的代理按照代理类生成时机不同分为静态代理和动态代理。静态代理是在编译时期就生成,而动态代理类则是在java运行时虚拟机内部自动生成。动态代理又有jdk代理和cglib代理两种

结构/角色

代理模式分为三种角色:

  • 抽象主题类:通过接口和抽象类声明真实主题和代理对象实现的业务方法
  • 真实主题类:实现了抽象主题的具体业务方法,是代理对象所要代表的真实对象(被代理对象/目标对象),是最终要引用的对象。
  • 代理类:提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制或者扩展真是主题的功能。

静态代理实现

1.抽象主题

public interface UserService {
    void update();

    void delete();

    void insert();
}

2.真实主题类

public class UserServiceImpl implements UserService {

    @Override
    public void update() {
        System.out.println("修改数据业务。。。");
    }

    @Override
    public void delete() {
        System.out.println("删除数据业务。。。");
    }

    @Override
    public void insert() {
        System.out.println("增加数据业务。。。");
    }
}

3.代理类

public class UserProxy implements UserService {
	//抽象主题的引用
    private UserService userService;

    public UserProxy(UserService userService) {
        this.userService = userService;
    }

	//扩展真实主题的功能
    @Override
    public void update() {
        System.out.println("增强代码");
        userService.update();
    }

    @Override
    public void delete() {
        System.out.println("增强代码");
        userService.delete();
    }

    @Override
    public void insert() {
        System.out.println("增强代码");
        userService.insert();
    }
}

动态代理(JDK)

  Java中提供了一个动态代理类Proxy,Proxy并不是我们上述所说的代理对象的类,而是提供了一个创建代理对象的静态方法(newProxyInstance方法)来获取代理对象(也实现了抽象主题)。
1.抽象主题

public interface OrderService {
    int update();

    void delete();

    void insert();
}

2.真实主题类

public class OrderServiceImpl implements OrderService{
    @Override
    public int update() {
        System.out.println("update业务处理中...");
        return 10;
    }

    @Override
    public void delete() {
        System.out.println("delete业务处理中...");
    }

    @Override
    public void insert() {
        System.out.println("insert业务处理中...");
    }
}

3.InvocationHandler的实现类(后面会将该类的作用)

public class TimerInvocationHandler implements InvocationHandler {

    private Object orderService;

    public TimerInvocationHandler() {}
    public TimerInvocationHandler(Object orderService) {
        this.orderService = orderService;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("执行invoke方法");
        System.out.println("增强代码1");
        Object invoke = method.invoke(orderService, args);//相当于调用真实主题类方法
        System.out.println("增强代码2");
        System.out.println("=============");
        return invoke;
    }
}

4.测试类

public class Client{
	public static void main(String[] args){
		//创建目标类对象或者真实主题类
		OrderService orderService = new OrderServiceImpl();
		//创建代理对象,虚拟机内部自动生成一个代理类,该类是实现了抽象主题接口的
		OrderService proxyInstance =(OrderService)Proxy.newProxyInstance(orderService.getClass().getClassLoader(),
									 									orderService.getClass().getInterfaces(),
									 									new TimerInvocationHandler(orderService))
	}
}
//解释:newProxyInstance方法三个参数:
//	arg1:类加载器,用于加载代理类,使用真实对象的类加载器即可
//	arg2: 真实对象所实现的接口,即代理模式真实对象和代理对象实现相同的接口
//	arg3: 代理对象的调用处理程序(而参数本身是一个接口类型,因此要自定义一个类(TimerInvocationHandler)来实现它

总结:jdk动态代理其实和动态代理产不多,区别只是一个手动的创建代理类,一个是程序运行时虚拟机自动给创建了代理类(它是通过Proxy的方法和其参数来确定构造代理类的),同时也帮代理类也实现类抽象主题接口。jdk动态代理只能代理接口,意思是必须有抽象主题接口,否则无法代理。而cglib恰好对其进行了补充,它为没有实现接口的类提供代理。
备注:spring的aop原理默认是基于jdk动态代理的,可以选择使用cglib

cglib动态代理-后续补充

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值