从Spring框架看设计模式如何灵活使用
Singleton 单例模式#
单例模式是确保每个应用程序只存在一个实例的机制。默认情况下,Spring将所有bean创建为单例。
你用@Autowired获取的bean,全局唯一。
@RestController
public class LibraryController {
@Autowired
private BookRepository repository;
@GetMapping("/count")
public Long findCount() {
System.out.println(repository);
return repository.count();
}
}
工厂方法模式#
Spring 定义了BeanFactory接口,抽象对象容器:
public interface BeanFactory {
getBean(Class<T> requiredType);
getBean(Class<T> requiredType, Object... args);
getBean(String name);
// ...
]
每一个getBean
方法其实就是一个工厂方法。
代理模式(Proxy)#
在Spring中,对于事务,我们可以加一个@Transactional
注解,
@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
的包装:
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
等方法时,增加了自己装饰逻辑在里面。
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
, 用于监控服务健康状态。
@FunctionalInterface
public interface HealthIndicator {
/**
* Return an indication of health.
* @return the health for
*/
Health health();
}
实现类里,有一个CompositeHealthIndicator
, 可以add
多个HealthIndicator
,放入indicators
里,最后返回health
时,聚合所有indicators
的Health
。
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);
}
}
感谢您的认真阅读。
如果你觉得有帮助,欢迎点赞支持!
不定期分享软件开发经验,欢迎关注作者, 一起交流软件开发:
关注作者
作者: JadePeng
出处:https://www.cnblogs.com/xiaoqi/p/spring-design-pattern.html
版权:本文采用「署名-非商业性使用-相同方式共享 4.0 国际(欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接) 」知识共享许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了