代理模式

代理模式

使用一个代理对象将对象包装起来,然后用该代理对象来取代该对象,任何对原始对象的调用都要通过代理,代理对象决定是否以及何时调用原始对象的方法 .

来源于这篇博客

以下例子来源于大神狂神!!!

1、静态代理

思维导图

1. Rent接口,负责出租房子的人和中介共同需要干的事出租房子

//租房
public interface Rent {
//租房子
public void rent();
}

2. Proxy表示中介去继承租房的接口

  • 房东只需要把房子交给中介就行了,有中介代理,中介有些自己的事情要做....
@Component(value = "proxy")
public class Proxy implements Rent{
@Autowired
@Qualifier("host")
private Host host;
public Proxy() {
}
public Proxy(Host host) {
this.host = host;
}
@Override
public void rent() {
lookHouse();
host.rent();
signContract();
harvestFees();
}
public void lookHouse(){
System.out.println("看" + host.getHostName() +"的房子");
}
public void signContract(){
System.out.println("签合同");
}
public void harvestFees(){
System.out.println("收中介费");
}
}

3. 房东Host,需要出租房屋,他就只干一件事,租房子

@Component(value = "host")
public class Host implements Rent{
private String hostName;
public String getHostName() {
return hostName;
}
public void setHostName(String hostName) {
this.hostName = hostName;
}
@Override
public void rent() {
System.out.println("房东要出租房");
}
}

4. 需要租房的人,People,需要找中介租房,不直接联系房东,由中介全权代理

//需要租房的人
public class People {
@Test
public void makeHouse(){
ApplicationContext context = new AnnotationConfigApplicationContext(SsyConfig.class);
Host host = context.getBean("host", Host.class);
host.setHostName("水三丫");
Proxy proxy = context.getBean("proxy", Proxy.class);
proxy.rent();
}
}
//运行结果
看水三丫的房子
房东要出租房
签合同
收中介费
Process finished with exit code 0

静态代理的缺点:一个真实的角色会参数一个代理角色,代码量会翻倍,需要动态代理来解决

2、动态代理

利用Java的反射技术(Java Reflection),在运行时创建一个实现某些给定接口的新类(也称“动态代理类”)及其实例(对象),代理的是接口(Interfaces),不是类(Class),也不是抽象类。在运行时才知道具体的实现,spring aop就是此原理。

参考一笑而过者也博客

2.1 需要了解两个类

  • Proxy:代理
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
  1. loader: 用哪个类加载器去加载代理对象

  2. interfaces:动态代理类需要实现的接口

  3. h:动态代理方法在执行时,会调用h里面的invoke方法去执行

  • InvocationHandler接口:调用处理程序

2.2 测试

  • 需要代理的接口
public interface UserService {
public void add();
public void update();
public void delete();
public void query();
}
  • 实现该接口的类
public class UserServiceImpl implements UserService{
@Override
public void add() {
System.out.println("增加了一个用户");
}
@Override
public void update() {
System.out.println("更新了一个用户");
}
@Override
public void delete() {
System.out.println("删除了一个用户");
}
@Override
public void query() {
System.out.println("查询了一个用户");
}
}
  • 实现该InvocationHandler接口的通过反射获取代理类的类
@Component("proxyInvocationHandler")
public class ProxyInvocationHandler implements InvocationHandler {
private Object target;
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
//生成代理类
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
//处理代理事例并返回结果,当代理类调用方法时会走这个method,invoke()
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method.getName());
before();
Object result = method.invoke(target, args);
after();
return result;
}
public void before(){
System.out.println("操作之前打印日志");
}
public void after(){
System.out.println("操作之后打印日志");
}
}
  • 需要操作的客户
public class UserServlet {
@Test
public void test(){
ApplicationContext context = new AnnotationConfigApplicationContext(SsyConfigService.class);
UserServiceImpl userServiceImpl = context.getBean("userService", UserServiceImpl.class);
ProxyInvocationHandler pih = context.getBean("proxyInvocationHandler", ProxyInvocationHandler.class);
pih.setTarget(userServiceImpl);
UserService proxy = (UserService) pih.getProxy();
proxy.update();
}
}
posted @   水三丫  阅读(36)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示