从Spring框架看设计模式如何灵活使用

Singleton 单例模式#

单例模式是确保每个应用程序只存在一个实例的机制。默认情况下,Spring将所有bean创建为单例。

单例模式

你用@Autowired获取的bean,全局唯一。

Copy
@RestController public class LibraryController { @Autowired private BookRepository repository; @GetMapping("/count") public Long findCount() { System.out.println(repository); return repository.count(); } }

工厂方法模式#

Spring 定义了BeanFactory接口,抽象对象容器:

Copy
public interface BeanFactory { getBean(Class<T> requiredType); getBean(Class<T> requiredType, Object... args); getBean(String name); // ... ]

每一个getBean 方法其实就是一个工厂方法。

代理模式(Proxy)#

代理模式

在Spring中,对于事务,我们可以加一个@Transactional注解,

Copy
@Service public class BookManager { @Autowired private BookRepository repository; @Transactional public Book create(String author) { System.out.println(repository.getClass().getName()); return repository.create(author); } }

Spring框架,通过AOP做Proxy。

Decorator装饰器模式#

Spring 中的TransactionAwareCacheDecorator 就做了对Cache 的包装:

Copy
public interface Cache { String getName(); Object getNativeCache(); @Nullable Cache.ValueWrapper get(Object var1); @Nullable <T> T get(Object var1, @Nullable Class<T> var2); @Nullable <T> T get(Object var1, Callable<T> var2); void put(Object var1, @Nullable Object var2); }

TransactionAwareCacheDecorator 实现了Cache接口,构造时传入一个targetCache,在调用put等方法时,增加了自己装饰逻辑在里面。

Copy
public class TransactionAwareCacheDecorator implements Cache { private final Cache targetCache; public TransactionAwareCacheDecorator(Cache targetCache) { Assert.notNull(targetCache, "Target Cache must not be null"); this.targetCache = targetCache; } public void put(final Object key, @Nullable final Object value) { if (TransactionSynchronizationManager.isSynchronizationActive()) { TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() { public void afterCommit() { TransactionAwareCacheDecorator.this.targetCache.put(key, value); } }); } else { this.targetCache.put(key, value); } }

最佳实践#

  • 装饰模式是继承的有力补充。相比于继承,装饰模式可以增加代码的可维护性、扩展性、复用性。在一些情况下装饰模式可以替代继承,解决类膨胀问题。

  • 装饰模式有利于程序的可扩展性。在一个项目中,有很多因素考虑不周,特别是业务的变更。通过装饰模式重新封装一个装饰类,可以避免修改继承体系中的中间类,而是使用装饰类修饰中间类,这样原有的程序没有变更,通过扩展完成了这次变更。

组合模式(Composite)#

Spring actuate 提供HealthIndicator, 用于监控服务健康状态。

Copy
@FunctionalInterface public interface HealthIndicator { /** * Return an indication of health. * @return the health for */ Health health(); }

实现类里,有一个CompositeHealthIndicator, 可以add多个HealthIndicator,放入indicators里,最后返回health时,聚合所有indicatorsHealth

Copy
public class CompositeHealthIndicator implements HealthIndicator { private final Map<String, HealthIndicator> indicators; private final HealthAggregator healthAggregator; /** * Create a new {@link CompositeHealthIndicator}. * @param healthAggregator the health aggregator */ public CompositeHealthIndicator(HealthAggregator healthAggregator) { this(healthAggregator, new LinkedHashMap<>()); } /** * Create a new {@link CompositeHealthIndicator} from the specified indicators. * @param healthAggregator the health aggregator * @param indicators a map of {@link HealthIndicator}s with the key being used as an * indicator name. */ public CompositeHealthIndicator(HealthAggregator healthAggregator, Map<String, HealthIndicator> indicators) { Assert.notNull(healthAggregator, "HealthAggregator must not be null"); Assert.notNull(indicators, "Indicators must not be null"); this.indicators = new LinkedHashMap<>(indicators); this.healthAggregator = healthAggregator; } public void addHealthIndicator(String name, HealthIndicator indicator) { this.indicators.put(name, indicator); } @Override public Health health() { Map<String, Health> healths = new LinkedHashMap<>(); for (Map.Entry<String, HealthIndicator> entry : this.indicators.entrySet()) { healths.put(entry.getKey(), entry.getValue().health()); } return this.healthAggregator.aggregate(healths); } }

感谢您的认真阅读。

如果你觉得有帮助,欢迎点赞支持!

不定期分享软件开发经验,欢迎关注作者, 一起交流软件开发:

关注作者

欢迎关注作者微信公众号, 一起交流软件开发:欢迎关注作者微信公众号

posted @   JadePeng  阅读(509)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示
CONTENTS