精心整理了设计模式——代理模式,并配图加代码,方便理解,实属不易,但是难免不了存在纰漏,感谢大家的指正与理解!觉的写的不错的小伙伴儿,一键三连支持一下,后期会有持续更新!!抱拳了罒ω罒
代理模式简介
- 代理模式:为其他对象提供一种代理以控制对这个对象的访问。通过代理就是不改变原有业务的基础上,对业务方法进行增强。
- 代理模式分为静态代理和动态代理;实现动态代理的方式有JDK 动态代理和CGLIB 动态代理
- 代码步骤:
- 接口;
- 真实角色(被代理角色);
- 代理角色;
- 客户(客户端访问代理角色);
1. 静态代理
我们以租客租客租房子为例,租客通过中介租住房东的房子,并从中获取中介费用。
Rent接口:抽象接口
//租房接口
public interface Rent {
public void rent();
}
Host 类:房东(被代理对象)要出租房子
class Host implements Rent{
@Override
public void rent() {
System.out.println("房东要出租房子!!!");
}
}
Proxy 类:中介(代理对象)替房东完成租房
class Proxy implements Rent{
private Host host;
public Proxy(Host host) {
this.host = host;
}
@Override
public void rent() {
System.out.println("中介带领客户看房");//对租房进行增强
host.rent();//进行租房
System.out.println("中介收中介费");//对租房再进行增强
}
}
演示:
class client{
public static void main(String[] args) {
Host host = new Host();//房东租房
Proxy proxy = new Proxy(host);//中介代替房东租房
proxy.rent(); //中介带领客户看房
//房东要出租房子!!!
//中介收中介费
}
}
存在的问题:代理类手动创建,如果需要代理的对象多了,那么代理类也越来越多。因此动态代理应运而生。
2. 动态代理——JDK 动态代理
如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP ,核心InvocationHandler接口和Proxy类,InvocationHandler 通过invoke()方法来调用目标类中的代码; Proxy利用 InvocationHandler创建的实例, 生成目标类的代理对象。
JDK 动态代理本质上是 实现了被代理对象的接口。
JDK动态生成的代理类已经继承了Proxy类, 由于java的单继承,所以只能靠实现被代理类的接口的形式,故JDK的动态代理必须有接口。
以在开发过程中实际应用为例说明。
UserService接口:定义查询用户的方法;
interface UserService{
//查询方法
public void select();
}
UserServiceImpl 类:UserService接口的实现;
class UserServiceImpl implements UserService{
@Override
public void select() {
System.out.println("查询一个用户");
}
}
JDKProxyInvocationHandler 类:JDK动态类的实现
class JDKProxyInvocationHandler implements InvocationHandler{
//真实对象,即被代理对象
private Object target;
public JDKProxyInvocationHandler(Object target) {
this.target = target;
}
//通过Proxy类,创建代理对象
public Object getProxy(){
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this);
}
//invoke方法,代理对象执行的增强的方法。
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("查询用户之前进行检验用户是否登录!");
Object invoke = method.invoke(target, args);
return invoke;
}
}
演示:
class client{
public static void main(String[] args) {
//真实对象,被代理对象
UserServiceImpl service = new UserServiceImpl();
//代理对象的创建
JDKProxyInvocationHandler handler = new JDKProxyInvocationHandler(service);
UserService proxy = (UserService) handler.getProxy();
//代理对象的增强方法
proxy.select();
//输出
//查询用户之前进行检验用户是否登录!
//查询一个用户
}
}
2. 动态代理——CGLIB 动态代理
如果目标对象没有实现接口,必须采用CGLIB,其主要是对指定的类生成一个子类,覆盖其中的方法。因为是继承,所以该类或方法最好不要声明成final。CGLIB 动态代理需要引入第三方的 jar 包。
以在开发过程中实际应用为例说明。UserService接口和UserServiceImpl 类是不变的。只需将代理类更改为CGLIB代理即可。
public class CglibProxyFactory implements MethodInterceptor {
// 目标对象(被代理对象)
private Object target;
public CglibProxyFactory(Object target) {
this.target = target;
}
// 创建代理对象
public Object createProxy() {
// 1.创建Enhancer
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
// 真正执行代理增强的方法
@Override
public Object intercept(Object o, Method method, Object[] objects,
MethodProxy methodProxy) throws Throwable {
System.out.println("查询用户之前进行检验用户是否登录!");
Object invoke = method.invoke(target, objects);
return invoke;
}
public static void main(String[] args) {
// 1.创建对象
UserServiceImpl service = new UserServiceImpl();
// 2.创建代理对象
CglibProxyFactory cglibProxyFactory = new CglibProxyFactory(service );
UserService userServiceProxy = (UserService)
cglibProxyFactory.createProxy();
//代理对象的增强方法
userServiceProxy.select();
//输出
//查询用户之前进行检验用户是否登录!
//查询一个用户
}
}
学习视频与参考文章:
https://www.bilibili.com/video/BV1mc411h719?p=11
https://csp1999.blog.csdn.net/article/details/117672843