Spring中的适配器模式和策略模式
创始人
2024-12-29 08:34:12
0

1. 适配器模式的应用

1.1适配器模式(Adapter Pattern)的原始定义是:将一个类的接口转换为客户期望的另一个接口,适配器可以让不兼容的两个类一起协同工作。

在这里插入图片描述

1.2 AOP中的适配器模式

在Spring的AOP中,使用Advice(通知)来增强被代理类的功能。Advice的类型有:BeforeAdvice、AfterReturningAdvice、ThrowsAdvice。每种Advice都有对应的拦截器,如MethodBeforeAdviceInterceptor、AfterReturningAdviceInterceptor、ThrowsAdviceInterceptor。

在这里插入图片描述

1.3 代码示例

以下示例展示了如何使用适配器模式在Spring AOP中增强一个目标类的功能。

public interface MyService {     void doSomething(); }  public class MyServiceImpl implements MyService {     @Override     public void doSomething() {         System.out.println("Doing something ...");     } }  // 使用Advice(通知)来增强被代理类的功能 public class MyBeforeAdvice implements MethodBeforeAdvice {     // 在目标方法执行前进行拦截     @Override     public void before(Method method, Object[] objects, Object o) throws Throwable {         System.out.println("我变强,也变秃了......");     } }  // 自定义适配器对象,将BeforeAdvice对象适配为一个MethodBeforeAdviceInterceptor对象 public class MyBeforeAdviceAdapter extends MethodBeforeAdviceInterceptor {     public MyBeforeAdviceAdapter(MethodBeforeAdvice advice) {         super(advice);     } }  public class Test01 {     public static void main(String[] args) {         // 创建前置通知对象         MyBeforeAdvice advice = new MyBeforeAdvice();         // 创建适配器对象,传入通知对象         MyBeforeAdviceAdapter adapter = new MyBeforeAdviceAdapter(advice);         // 获取目标对象的代理工厂         ProxyFactory factory = new ProxyFactory(new MyServiceImpl());         // 向代理对象中添加适配器对象         factory.addAdvice(adapter);         // 获取代理对象         MyService proxy = (MyService) factory.getProxy();         // 调用代理方法         proxy.doSomething();     } } 

每个类对应适配器模式中的如下角色:

  1. TargetMyServiceImpl类是目标对象,即需要被代理的对象。
  2. AdapterMyBeforeAdviceAdapter类是适配器对象,它将 MyBeforeAdvice对象适配为一个 MethodBeforeAdviceInterceptor对象,使得 MyBeforeAdvice可以被应用到目标对象的代理中。
  3. AdapteeMyBeforeAdvice类是被适配的对象,它定义了一个前置通知方法,在目标方法执行前进行拦截。
  4. ClientTest01类是客户端,它通过创建适配器对象并将其添加到目标对象的代理中,实现了在目标方法执行前应用 MyBeforeAdvice的前置通知。
    在这里插入图片描述

2. 策略模式的应用

策略模式是一种行为设计模式,它允许定义一系列算法,将每个算法分别封装起来,并使它们可以相互替换。这种模式使得算法可以在不影响客户端的情况下发生变化。在Spring框架中,策略模式的应用十分广泛,下面是Resource接口及其实现类的示例。

2.1 Resource 接口

Spring框架的资源访问Resource接口提供了强大的资源访问能力。Spring框架本身大量使用了Resource接口来访问底层资源。Resource接口本身没有提供访问任何底层资源的实现逻辑,而是针对不同的底层资源提供了不同的Resource实现类,这些实现类负责不同的资源访问逻辑。

Spring为Resource接口提供了如下实现类:

  • UrlResource:访问网络资源的实现类。
  • ClassPathResource:访问类加载路径里的资源的实现类。
  • FileSystemResource:访问文件系统里的资源的实现类。
  • ServletContextResource:访问相对于ServletContext路径里的资源的实现类。
  • InputStreamResource:访问输入流资源的实现类。
  • ByteArrayResource:访问字节数组资源的实现类。

这些Resource实现类针对不同的底层资源提供了相应的资源访问逻辑,并提供便捷的包装,以便客户端程序的资源访问。

public class ResourceTest {      public static void main(String[] args) throws IOException {         // 创建ClassPathResource对象         Resource resource = new ClassPathResource("application.properties");          // 调用getInputStream()方法读取资源         InputStream is = resource.getInputStream();          byte[] bytes = new byte[1024];         int n;         while ((n = is.read(bytes)) != -1) {             System.out.println(new String(bytes, 0, n));         }         is.close();     } } 

2.2 DefaultResourceLoader

ResourceLoader接口用于返回Resource对象,其实现可以看作是一个生产Resource的工厂类。当创建Resource对象时,Spring会根据传入的资源路径来选择相应的Resource实现类。这一过程是由Spring中的ResourceLoader接口及其实现类DefaultResourceLoader来完成的。

DefaultResourceLoader中的getResource方法会根据传入的资源路径选择相应的Resource实现类,从而实现了策略模式的效果。

public Resource getResource(String location) {     Assert.notNull(location, "Location must not be null");      // 遍历ProtocolResolver集合,通过ProtocolResolver来解析资源路径     for (ProtocolResolver protocolResolver : this.getProtocolResolvers()) {         Resource resource = protocolResolver.resolve(location, this);         if (resource != null) {             return resource;         }     }      // 没有找到对应的ProtocolResolver,使用默认的处理方式     if (location.startsWith("/")) {         // 以斜杠开头的路径,表示基于ServletContext的相对路径         return this.getResourceByPath(location);     } else if (location.startsWith("classpath:")) {         // 以classpath:开头的路径,表示在classpath下查找资源         return new ClassPathResource(location.substring("classpath:".length()), this.getClassLoader());     } else {         try {             // 尝试将路径解析为URL,如果是文件URL则创建FileUrlResource,否则创建UrlResource             URL url = new URL(location);             return (Resource) (ResourceUtils.isFileURL(url) ? new FileUrlResource(url) : new UrlResource(url));         } catch (MalformedURLException var5) {             // 如果路径无法解析为URL,则当做相对路径来处理             return this.getResourceByPath(location);         }     } } 

在上述代码中,getResource方法根据传入的资源路径选择相应的Resource实现类,从而实现了策略模式的效果。不同的实现类负责不同类型资源的访问逻辑,使得Resource接口的使用更加灵活和便捷。

相关内容

热门资讯

一分钟内幕!科乐吉林麻将系统发... 一分钟内幕!科乐吉林麻将系统发牌规律,福建大玩家确实真的是有挂,技巧教程(有挂ai代打);所有人都在...
一分钟揭秘!微扑克辅助软件(透... 一分钟揭秘!微扑克辅助软件(透视辅助)确实是有挂(2024已更新)(哔哩哔哩);1、用户打开应用后不...
五分钟发现!广东雀神麻雀怎么赢... 五分钟发现!广东雀神麻雀怎么赢,朋朋棋牌都是是真的有挂,高科技教程(有挂方法)1、广东雀神麻雀怎么赢...
每日必看!人皇大厅吗(透明挂)... 每日必看!人皇大厅吗(透明挂)好像存在有挂(2026已更新)(哔哩哔哩);人皇大厅吗辅助器中分为三种...
重大科普!新华棋牌有挂吗(透视... 重大科普!新华棋牌有挂吗(透视)一直是有挂(2021已更新)(哔哩哔哩)1、完成新华棋牌有挂吗的残局...
二分钟内幕!微信小程序途游辅助... 二分钟内幕!微信小程序途游辅助器,掌中乐游戏中心其实存在有挂,微扑克教程(有挂规律)二分钟内幕!微信...
科技揭秘!jj斗地主系统控牌吗... 科技揭秘!jj斗地主系统控牌吗(透视)本来真的是有挂(2025已更新)(哔哩哔哩)1、科技揭秘!jj...
1分钟普及!哈灵麻将攻略小,微... 1分钟普及!哈灵麻将攻略小,微信小程序十三张好像存在有挂,规律教程(有挂技巧)哈灵麻将攻略小是一种具...
9分钟教程!科乐麻将有挂吗,传... 9分钟教程!科乐麻将有挂吗,传送屋高防版辅助(总是存在有挂)1、完成传送屋高防版辅助透视辅助安装,帮...
每日必看教程!兴动游戏辅助器下... 每日必看教程!兴动游戏辅助器下载(辅助)真是真的有挂(2025已更新)(哔哩哔哩)1、打开软件启动之...