容器概述
控制反轉(zhuǎn)(IoC)也稱為依賴注入(DI),它是一個(gè)過(guò)程。對(duì)象(Bean)通過(guò)構(gòu)造方法、工廠方法、屬性設(shè)置依賴項(xiàng),然后容器在創(chuàng)建對(duì)象(Bean)時(shí),注入這些依賴項(xiàng)。此過(guò)程從根本上說(shuō)是通過(guò)設(shè)置的依賴項(xiàng)去查找對(duì)象(Bean)而不是我們主動(dòng)去設(shè)置(因此稱為控制翻轉(zhuǎn))。

IOC容器
BeanFactory
-
org.springframework.beans中默認(rèn)實(shí)現(xiàn)DefaultListableBeanFactory類圖
DefaultListableBeanFactory類圖.png
ApplicationContext
-
類圖
ApplicationContext類圖.png
Environment
-
來(lái)看下servlet的環(huán)境StandardServletEnvironment類圖
StandardServletEnvironment類圖.png -
Environment是在初始化時(shí)AbstractEnvironment調(diào)用鉤子方法customizePropertySources把對(duì)應(yīng)環(huán)境加進(jìn)去的,下面我們來(lái)看下相應(yīng)的代碼
- AbstractEnvironment
public abstract class AbstractEnvironment implements ConfigurableEnvironment {
......
/**
* Create a new {@code Environment} instance, calling back to
* {@link #customizePropertySources(MutablePropertySources)} during construction to
* allow subclasses to contribute or manipulate {@link PropertySource} instances as
* appropriate.
* @see #customizePropertySources(MutablePropertySources)
*/
public AbstractEnvironment() {
//初始化時(shí),子類添加環(huán)境
customizePropertySources(this.propertySources);
}
protected void customizePropertySources(MutablePropertySources propertySources) {
//空方法,子類需要添加環(huán)境時(shí)覆蓋
}
......
}
- StandardEnvironment
public class StandardEnvironment extends AbstractEnvironment {
/** System environment property source name: {@value}. */
public static final String SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME = "systemEnvironment";
/** JVM system properties property source name: {@value}. */
public static final String SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME = "systemProperties";
/**
* Customize the set of property sources with those appropriate for any standard
* Java environment:
* <ul>
* <li>{@value #SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME}
* <li>{@value #SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME}
* </ul>
* <p>Properties present in {@value #SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME} will
* take precedence over those in {@value #SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME}.
* @see AbstractEnvironment#customizePropertySources(MutablePropertySources)
* @see #getSystemProperties()
* @see #getSystemEnvironment()
*/
@Override
protected void customizePropertySources(MutablePropertySources propertySources) {
//添加JVM 環(huán)境變量,我們平時(shí)在idea和tomcat里面寫的-D參數(shù)
propertySources.addLast(
new PropertiesPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
//電腦的環(huán)境變量
propertySources.addLast(
new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
}
}
- StandardServletEnvironment
public class StandardServletEnvironment extends StandardEnvironment implements ConfigurableWebEnvironment {
@Override
protected void customizePropertySources(MutablePropertySources propertySources) {
......
// 添加servletConfigInitParams環(huán)境,web.xml里面寫的init-param
propertySources.addLast(new StubPropertySource(SERVLET_CONFIG_PROPERTY_SOURCE_NAME));
// 添加servletContextInitParams環(huán)境,web.xml里面寫的context-param
propertySources.addLast(new StubPropertySource(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME));
// 添加jndiProperties環(huán)境,配置數(shù)據(jù)庫(kù)的,一般寫在tomcat里面的resource
if (JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()) {
propertySources.addLast(new JndiPropertySource(JNDI_PROPERTY_SOURCE_NAME));
}
//調(diào)用父類,添加標(biāo)準(zhǔn)環(huán)境
super.customizePropertySources(propertySources);
}
......
}
統(tǒng)一資源加載策略
Resource
Java自帶的java.net.URL類不足以滿足所有對(duì)低級(jí)資源的訪問(wèn),比如沒(méi)有標(biāo)準(zhǔn)化的URL實(shí)現(xiàn)可用于訪問(wèn)需要從類路徑或相對(duì)于ServletContext獲得的資源。Spring的Resource接口旨在成為一種功能更強(qiáng)大的接口,用于抽象化對(duì)低級(jí)資源的訪問(wèn)。下面來(lái)看下幾個(gè)常用resource的類圖

ResourceLoader

-
返回多個(gè)資源的ResourcePatternResolver
ResourcePatternResolver類圖.png
ApplicationContext分析
ClassPathXmlApplicationContext時(shí)序圖
-
加載BeanDefinition時(shí)序圖
xml加載BeanDefinition.png -
實(shí)例化時(shí)序圖
實(shí)例會(huì).png
AbstractApplicationContext的refresh方法
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
// 裝備刷新方法,時(shí)間、環(huán)境、事件這些
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
// 告訴子類刷新BeanFactory,加載BeanDefinition,獲取最新的BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
// 準(zhǔn)備BeanFactory,類加載器、忽略接口、屬性解析等
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
// 為某些子類預(yù)留的BeanFactory后置處理
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
// 執(zhí)行BeanFactoryPostProcessor后置處理
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 注冊(cè)掃描到的BeanPostProcessor到應(yīng)用上下文
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
// 初始化所有剩余的單例bean
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
ApplicationContext擴(kuò)展點(diǎn)
FactoryBean
FactoryBean是實(shí)現(xiàn)了org.springframework.beans.factory.FactoryBean<T>接口的Bean,從ApplicationContext的getBean()方法獲取的對(duì)象不是該類的一個(gè)實(shí)例,而是該類的getObject()方法所返回的對(duì)象。
當(dāng)我們需要獲取FactoryBean實(shí)例本身而不是它所產(chǎn)生的bean,則要使用'&'符號(hào)。
當(dāng)有復(fù)雜的初始化場(chǎng)景,比如返回propertySource、mybatis的代理類
BeanFactoryPostProcess
當(dāng)BeanFactory加載完成BeanDefinition之后,對(duì)BeanDefinition的后置處理
BeanPostProcess
當(dāng)對(duì)象new出來(lái),在執(zhí)行init方法之前和之后執(zhí)行
public interface BeanPostProcessor {
// init方法之前
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
// init方式之后
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}





