四、设计模式在框架中的实战
精通框架的另一个标志是能识别并理解框架中运用的设计模式。
4.1 工厂模式 —— BeanFactory
// BeanFactory是最顶层的工厂接口
public interface BeanFactory {
Object getBean(String name) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
}
4.2 模板方法模式 —— JdbcTemplate
JdbcTemplate将数据库操作的固定流程(获取连接、创建Statement、执行、处理结果、关闭资源)封装在模板方法中,而将变化的部分(SQL语句、结果集映射)留给回调实现:
// 简化版JdbcTemplate
public class JdbcTemplate {
public <T> T query(String sql, RowMapper<T> rowMapper) {
// 固定流程
Connection conn = getConnection();
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
// 变化部分交给回调
T result = rowMapper.mapRow(rs);
// 固定关闭
close(rs, ps, conn);
return result;
}
}
4.3 适配器模式 —— HandlerAdapter
Spring MVC中,为什么@Controller、HttpRequestHandler、Servlet都可以作为处理器?因为HandlerAdapter做了适配:
public interface HandlerAdapter {
boolean supports(Object handler);
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
}
// 针对不同Handler的实现
public class RequestMappingHandlerAdapter implements HandlerAdapter { ... }
public class SimpleControllerHandlerAdapter implements HandlerAdapter { ... }
4.4 观察者模式 —— ApplicationListener & ApplicationEvent
Spring的事件机制是观察者模式的典范:
// 自定义事件
public class OrderCreatedEvent extends ApplicationEvent {
private final String orderId;
public OrderCreatedEvent(Object source, String orderId) {
super(source);
this.orderId = orderId;
}
}
// 监听器
@Component
public class OrderEventListener {
@EventListener
public void handleOrderCreated(OrderCreatedEvent event) {
System.out.println("收到订单创建事件:" + event.getOrderId());
// 发送短信、更新统计等
}
}
// 发布事件
applicationContext.publishEvent(new OrderCreatedEvent(this, orderId));
底层原理:SimpleApplicationEventMulticaster遍历监听器列表,通过线程池异步或同步调用。
五、Spring Boot的自动配置 —— 走向约定的巅峰
Spring Boot通过“约定优于配置”极大降低了使用门槛,其灵魂在于@EnableAutoConfiguration。
5.1 @SpringBootApplication 组合注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@SpringBootConfiguration
@EnableAutoConfiguration // 核心!
@ComponentScan
public @interface SpringBootApplication {
}
5.2 @EnableAutoConfiguration 源码
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class) // 关键
public @interface EnableAutoConfiguration {
}
AutoConfigurationImportSelector的selectImports()方法会读取所有META-INF/spring.factories文件,获取org.springframework.boot.autoconfigure.EnableAutoConfiguration键对应的配置类列表。
5.3 spring.factories 示例(摘自spring-boot-autoconfigure)
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
5.4 条件注解体系
Spring Boot利用一系列@Conditional注解实现按需加载:
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RedisOperations.class) // classpath中有RedisOperations才加载
@EnableConfigurationProperties(RedisProperties.class) // 绑定配置
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
常用条件注解:
@ConditionalOnClass / @ConditionalOnMissingClass
@ConditionalOnBean / @ConditionalOnMissingBean
@ConditionalOnProperty(如spring.redis.host是否存在)
@ConditionalOnWebApplication
5.5 手写一个简单的Starter
要理解自动配置,不妨自己实现一个Starter:
# pom.xml 命名规范:xxx-spring-boot-starter
// 配置属性类
@ConfigurationProperties(prefix = "sms")
public class SmsProperties {
private String appId;
private String secret;
// getters/setters
}
// 服务类
public class SmsService {
public void send(String phone, String content) {
System.out.println("发送短信到 " + phone + ":" + content);
}
}
// 自动配置类
@Configuration
@ConditionalOnClass(SmsService.class)
@EnableConfigurationProperties(SmsProperties.class)
public class SmsAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public SmsService smsService(SmsProperties properties) {
SmsService service = new SmsService();
// 可以初始化properties中的配置
return service;
}
}
// src/main/resources/META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.sms.SmsAutoConfiguration
其他项目引入这个Starter后,只需要配置sms.app-id和sms.secret,就可以@Autowired使用SmsService。
来源:
http://dffne.cn/