友情链接:设计模式的使用:https://blog.csdn.net/qq_37248504/article/details/122991309
SpringBoot
中的BeanFactory
就是简单工厂模式的体现,根据传入一个唯一的标识来获得Bean
对象,但是否是在传入参数后创建还是传入参数前创建这个要根据具体情况来定。实现较为简单不做举例说明
容器的启动过程详见:https://blog.csdn.net/qq_37248504/article/details/123509139
使用示例:FactoryBean
接口。
SpringBoot
中体现就是Mybatis
mapper
中方法的实现,mapper
接口并没有具体的实现类,但是在注入的时候并不会报错,Mybatis
结合代理模式,在 getObject()
中返回一个代理的Bean
FactoryBean
接口,重写getObject()
,这个方法返回的是一个具体的Bean
,而不是 FactoryBean
getObject()
中返回一个代理对象的Bean
public class EngineFactory implements FactoryBean<CarEngine>, BeanNameAware, InvocationHandler {
private static final Logger logger = LoggerFactory.getLogger(EngineFactory.class);
private String name;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("fire".equalsIgnoreCase(method.getName())) {
logger.info(LogConst.LOG_SUCCESS_PREFIX + "here is invoke engine:" + method.getName());
}
if ("close".equalsIgnoreCase(method.getName())) {
logger.info(LogConst.LOG_SUCCESS_PREFIX + "here is invoke engine:" + method.getName());
}
return null;
}
@Override
public void setBeanName(String name) {
this.name = name;
}
/**
* 获取引擎 CarEngine 的代理对象
*
* @return
*/
@Override
public CarEngine getObject() {
logger.info(LogConst.LOG_SUCCESS_PREFIX + "EngineFactory to build Engine01 , EngineFactory :" + name);
CarEngine carEngine = (CarEngine) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{CarEngine.class}, this);
return carEngine;
}
@Override
public Class<?> getObjectType() {
return CarEngine.class;
}
/**
* 是否是单例 Bean
*
* @return
*/
@Override
public boolean isSingleton() {
return true;
}
}
FactoryBean
中获取Bean
的时候使用单例模式@Autowired
private ApplicationContext applicationContext;
Object testService = applicationContext.getBean("testServiceImpl");
FactoryBean
的getBean
方法再获取容器中Bean
的时候使用了单例模式//一级缓存:用于存放完全初始化好的 bean,从该缓存中取出的 bean 可以直接使用
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
// 二级缓存:提前曝光的单例对象的cache,存放原始的 bean 对象(尚未填充属性),用于解决循环依赖
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
// 三级缓存:单例对象工厂的cache,存放 bean 工厂对象,用于解决循环依赖
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 检查缓存中是否存在实例
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 提前曝光的单例对象的缓存中获取Bean
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
//如果为空,则锁定全局变量并进行处理。
synchronized (this.singletonObjects) {
// 在完整的单例锁中一致地创建早期引用
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
//当某些方法需要提前初始化的时候则会调用addSingleFactory 方法将对应的ObjectFactory初始化策略存储在singletonFactories
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 调用预先设定的getObject方法
singletonObject = singletonFactory.getObject();
// 放在缓存中
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
Wrapper
)模式,它既可以作为类结构型模式,也可以作为对象结构型模式。在适配器模式定义中所提及的接口是指广义的接口,它可以表示一个方法或者方法的集合。Spring AOP
的 AdvisorAdapter
类有 4 个实现类,即 SimpleBeforeAdviceAdapter
、MethodBeforeAdviceAdapter
、AfterReturningAdviceAdapter
和 ThrowsAdviceAdapter
Spring
会根据不同的 AOP
配置来确定使用对应的 Advice
,与策略模式不同的是,一个方法可以同时拥有多个 Advice
。@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 准备刷新的上下文,系统属性以及环境变量等
prepareRefresh();
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
prepareBeanFactory(beanFactory);
try {
postProcessBeanFactory(beanFactory);
invokeBeanFactoryPostProcessors(beanFactory);
registerBeanPostProcessors(beanFactory);
initMessageSource();
initApplicationEventMulticaster();
onRefresh();
registerListeners();
finishBeanFactoryInitialization(beanFactory);
finishRefresh();
}
}
}
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
}
jdbcTemplate
只需写sql
,然后对执行结果进行处理,省去了建立数据库连接与连接释放资源的重复操作,其中用的是模板方法设计模式,把重复的动作封装起来,需要处理的部分开放接口,让调用者去实现。public abstract class MyJdbcTemplate {
private static final Logger logger = LoggerFactory.getLogger(MyJdbcTemplate.class);
/**
* 数据源
*/
private DataSource dataSource;
/**
* 构造方法初始化 dataSource
*
* @param dataSource 数据源
*/
public MyJdbcTemplate(DataSource dataSource) {
this.dataSource = dataSource;
}
/**
* Jdbc Sql 查询过程
*
* @param sql sql
* @param values values
* @return List
*/
public final List<?> executeQuery(String sql, Object[] values) {
try {
Connection connection = this.getConnection();
PreparedStatement pre = this.createPrepareStatement(connection, sql);
ResultSet resultSet = this.executeQuery(pre, values);
List<Object> result = new ArrayList<>();
while (resultSet.next()) {
result.add(rowMapper(resultSet));
}
resultSet.close();
pre.close();
connection.close();
return result;
} catch (Exception exception) {
logger.error("Error occurred :", exception);
}
return null;
}
/**
* 由子类实现
*
* @param resultSet
* @return
* @throws SQLException
*/
protected abstract Object rowMapper(ResultSet resultSet) throws SQLException;
/**
* 执行查询
*
* @param preparedStatement preparedStatement
* @param values values
* @return ResultSet
* @throws SQLException
*/
private ResultSet executeQuery(PreparedStatement preparedStatement, Object[] values) throws SQLException {
for (int i = 0; i < values.length; i++) {
preparedStatement.setObject(i, values[i]);
}
return preparedStatement.executeQuery();
}
/**
* 对 SQL 语句进行预编译的操作
*
* @param connection connection
* @param sql sql
* @return PreparedStatement
* @throws SQLException
*/
private PreparedStatement createPrepareStatement(Connection connection, String sql) throws SQLException {
return connection.prepareStatement(sql);
}
/**
* 获取连接
*
* @return Connection
* @throws SQLException
*/
private Connection getConnection() throws SQLException {
return this.dataSource.getConnection();
}
}
Spring
事件驱动模型就是观察者模式很经典的一个应用。Spring
事件驱动模型非常有用,在很多场景都可以解耦我们的代码。spring-context
下默认的事件ContextStartedEvent
:ApplicationContext
启动后触发的事件;ContextStoppedEvent
:ApplicationContext
停止后触发的事件;ContextRefreshedEvent
:ApplicationContext
初始化或刷新完成后触发的事件;ContextClosedEvent
:ApplicationContext
关闭后触发的事件。ApplicationListener
充当了事件监听者角色,它是一个接口,里面只定义了一个 onApplicationEvent()
方法来处理ApplicationEvent
。ApplicationListener
接口类源码如下,可以看出接口定义看出接口中的事件只要实现了 ApplicationEvent
就可以了。所以,在 Spring
中我们只要实现 ApplicationListener
接口实现 onApplicationEvent()
方法即可完成监听事件public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
/**
* Handle an application event.
* @param event the event to respond to
*/
void onApplicationEvent(E event);
}
ApplicationEventPublisher
充当了事件的发布者,它也是一个接口。public interface ApplicationEventPublisher {
default void publishEvent(ApplicationEvent event) {
publishEvent((Object) event);
}
void publishEvent(Object event);
}
SpringBoot
使用事件示例见:https://blog.csdn.net/qq_37248504/article/details/115269995
getObject()
:ProxyFactoryBean
的 getObject
初始化通知链,然后根据通知生成实例对象public Object getObject() throws BeansException {
initializeAdvisorChain();
if (isSingleton()) {
return getSingletonInstance();
}
else {
if (this.targetName == null) {
logger.info("Using non-singleton proxies with singleton targets is often undesirable. " +
"Enable prototype proxies by setting the 'targetName' property.");
}
return newPrototypeInstance();
}
}
getSingletonInstance
:获取代理,然后获取实例//创建Aop动态代理,然后获取实例
this.singletonInstance = getProxy(createAopProxy());
详细见: https://blog.csdn.net/qq_37248504/article/details/108371768
Resource
接口是具体资源访问策略的抽象,也是所有资源访问类所实现的接口。public interface Resource extends InputStreamSource {
// 返回 Resource 所指向的资源是否存在
boolean exists();
default boolean isReadable() {
return exists();
}
// 返回 Resource 所指向的资源是否存在
default boolean isOpen() {
return false;
}
default boolean isFile() {
return false;
}
// 返回 Resource 所指向的资源是否存在
URL getURL() throws IOException;
URI getURI() throws IOException;
// 返回 Resource 所指向的资源是否存在
File getFile() throws IOException;
default ReadableByteChannel readableChannel() throws IOException {
return Channels.newChannel(getInputStream());
}
long contentLength() throws IOException;
long lastModified() throws IOException;
Resource createRelative(String relativePath) throws IOException;
@Nullable
String getFilename();
// 返回资源的描述信息,通常用于资源处理出错时输出该信息,通常是全限定文件名或实际 URL
String getDescription();
}
Resource
接口本身没有提供访问任何底层资源的实现逻辑,针对不同的底层资源,Spring
将会提供不同的 Resource
实现类,不同的实现类负责不同的资源访问逻辑。Spring
为 Resource
接口提供了如下实现类:
UrlResource
:访问网络资源的实现类。ClassPathResource
:访问类加载路径里资源的实现类FileSystemResource
:访问文件系统里资源的实现类。ServletContextResource
:访问相对于 ServletContext
路径里的资源的实现类InputStreamResource
:访问输入流资源的实现类。ByteArrayResource
:访问字节数组资源的实现类。提供访问任何底层资源的实现逻辑,针对不同的底层资源,Spring
将会提供不同的 Resource
实现类,不同的实现类负责不同的资源访问逻辑。