IOC思想解析
IOC(控制反转):全称为:Inverse of Control。从字面上理解就是控制反转了,将对在自身对象中的一个内置对象的控制反转,反转后不再由自己本身的对象进行控制这个内置对象的创建,而是由第三方系统去控制这个内置对象的创建。
DI(依赖注入):全称为Dependency Injection,意思自身对象中的内置对象是通过注入的方式进行创建。
那么IOC和DI这两者又是什么关系呢?
IOC就是一种软件设计思想,DI是这种软件设计思想的一个实现。
把本来在类内部控制的对象,反转到类外部进行创建后注入,不再由类本身进行控制,这就是IOC的本质。
xml方式配置bean
利用<bean>标签进行注入
<bean id="..." class="...">
<constructor-arg index="0" value="..."></constructor-arg>
<property name="..." value="..."></property>
<property name="...">
<list>
<value>...</value>
<value>...</value>
</list>
</property>
</bean>
优点:
- 低耦合
- 对象关系清晰
- 集中管理
缺点:
- 配置繁琐
- 开发效率较低
- 文件解析耗时
注解方式配置bean
1、使用@Component声明
2、配置类中使用@Bean
3、实现FactoryBean
@Component
public class MyCat implements FactoryBean<Animal> {
@Override
public Animal getObject() throws Exception {
return new Cat();
}
@Override
public Class<?> getObjectType() {
return Animal.class;
}
}
4、实现BeanDefinitionRegistryPostProcessor
@Component
public class MyBeanRegister implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition();
rootBeanDefinition.setBeanClass(Dog.class);
beanDefinitionRegistry.registerBeanDefinition("dog",rootBeanDefinition);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
}
}
5、实现ImportBeanDefinitionRegistry
public class MyBeanImport implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition();
rootBeanDefinition.setBeanClass(Bird.class);
registry.registerBeanDefinition("bird",rootBeanDefinition);
}
}
@Component
public class HelloService {
@Autowired
@Qualifier("bird")
private Animal animal;
public String hello(){
return animal.getName();
}
}
@RunWith(SpringRunner.class)
@SpringBootTest
@Import(MyBeanImport.class)
public class ApplicationTest {
@Autowired
private HelloService helloService;
@Test
public void test(){
System.out.println(helloService.hello());
}
}
优点:
- 使用简单
- 开发效率高
- 高内聚
缺点:
- 配置分散
- 对象关系不清晰
- 修改配置需要重新编译工程
refresh方法解析
完成了SpringApplication的run方法:
public ConfigurableApplicationContext run(String... args) {
// 计时工具
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
this.configureHeadlessProperty();
// 第一步:获取并启动监听器
SpringApplicationRunListeners listeners = this.getRunListeners(args);
listeners.starting();
Collection exceptionReporters;
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 第二步:根据SpringApplicationRunListeners以及参数来准备环境
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
this.configureIgnoreBeanInfo(environment);
// 准备Banner打印器 - 就是启动Spring Boot的时候打印在console上的ASCII艺术字体
Banner printedBanner = this.printBanner(environment);
// 第三步:创建Spring容器
context = this.createApplicationContext();
exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
// 第四步:Spring容器前置处理
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
// 第五步:刷新容器
this.refreshContext(context);
// 第六步:Spring容器后置处理
this.afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
}
// 第七步:发出结束执行的事件
listeners.started(context);
this.callRunners(context, applicationArguments);
} catch (Throwable var10) {
this.handleRunFailure(context, var10, exceptionReporters, listeners);
throw new IllegalStateException(var10);
}
try {
// 第八步:执行Runners
listeners.running(context);
// 返回容器
return context;
} catch (Throwable var9) {
this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
throw new IllegalStateException(var9);
}
}
- 第一步:获取并启动监听器
- 第二步:根据SpringApplicationRunListeners以及参数来准备环境
- 第三步:创建Spring容器
- 第四步:Spring容器前置处理
- 第五步:刷新容器
- 第六步:Spring容器后置处理
- 第七步:发出结束执行的事件
- 第八步:执行Runners
这里从创建Spring容器说起:
context = createApplicationContext();
继续跟进该方法:
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch (this.webApplicationType) {
case SERVLET:
contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
break;
case REACTIVE:
contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
break;
default:
contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
}
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, " + "please specify an ApplicationContextClass",
ex);
}
}
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}
这里创建容器的类型 还是根据webApplicationType进行判断的,该类型为SERVLET类型,所以会通过反射装载对应的字节码,也就是AnnotationConfigServletWebServerApplicationContext
第四步:Spring容器前置处理
这一步主要是在容器刷新之前的准备动作。包含一个非常关键的操作:将启动类注入容器,为后续开启自动化配置奠定基础。
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
继续跟进该方法:
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
//设置容器环境,包括各种变量
context.setEnvironment(environment);
//执行容器后置处理
postProcessApplicationContext(context);
//执行容器中的ApplicationContextInitializer(包括 spring.factories和自定义的实例)
applyInitializers(context);
//发送容器已经准备好的事件,通知各监听器
listeners.contextPrepared(context);
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
//注册启动参数bean,这里将容器指定的参数封装成bean,注入容器
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
//设置banner
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
// Load the sources
//获取我们的启动类指定的参数,可以是多个
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
//加载我们的启动类,将启动类注入容器
load(context, sources.toArray(new Object[0]));
//发布容器已加载事件。
listeners.contextLoaded(context);
}
调用初始化器:
protected void applyInitializers(ConfigurableApplicationContext context) {
// 1. 从SpringApplication类中的initializers集合获取所有的ApplicationContextInitializer
for (ApplicationContextInitializer initializer : getInitializers()) {
// 2. 循环调用ApplicationContextInitializer中的initialize方法
Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),
ApplicationContextInitializer.class);
Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
initializer.initialize(context);
}
}
这里终于用到了在创建SpringApplication实例时设置的初始化器了,依次对它们进行遍历,并调用initialize方法。我们也可以自定义初始化器,并实现initialize方法,然后放入META-INF/spring.factories配置文件中Key为:org.springframework.context.ApplicationContextInitializer的value中,这里我们自定义的初始化器就会被调用,是我们项目初始化的一种方式
加载启动指定类(重点)
大家先回到文章最开始看看,在创建SpringApplication实例时,先将HelloWorldMainApplication.class存储在this.primarySources属性中,现在就是用到这个属性的时候了,我们来看看getAllSources()
public Set<Object> getAllSources() {
Set<Object> allSources = new LinkedHashSet<>();
if (!CollectionUtils.isEmpty(this.primarySources)) {
//获取primarySources属性,也就是之前存储的HelloWorldMainApplication.class
allSources.addAll(this.primarySources);
}
if (!CollectionUtils.isEmpty(this.sources)) {
allSources.addAll(this.sources);
}
return Collections.unmodifiableSet(allSources);
}
很明显,获取了this.primarySources属性,也就是我们的启动类HelloWorldMainApplication.class,我们接着看load(context, sources.toArray(new Object[0]));
protected void load(ApplicationContext context, Object[] sources) {
if (logger.isDebugEnabled()) {
logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
}
BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources);
if (this.beanNameGenerator != null) {
loader.setBeanNameGenerator(this.beanNameGenerator);
}
if (this.resourceLoader != null) {
loader.setResourceLoader(this.resourceLoader);
}
if (this.environment != null) {
loader.setEnvironment(this.environment);
}
loader.load();
}
private int load(Class<?> source) {
if (isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
// Any GroovyLoaders added in beans{} DSL can contribute beans here
GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class);
load(loader);
}
if (isComponent(source)) {
//以注解的方式,将启动类bean信息存入beanDefinitionMap,也就是将Application.class存入了beanDefinitionMap
this.annotatedReader.register(source);
return 1;
}
return 0;
}
启动类Application.class被加载到 beanDefinitionMap中,后续该启动类将作为开启自动化配置的入口,后面一篇文章我会详细的分析,启动类是如何加载,以及自动化配置开启的详细流程。
通知监听器,容器已准备就绪
listeners.contextLoaded(context);
主还是针对一些日志等监听器的响应处理。
第五步:刷新容器
执行到这里,springBoot相关的处理工作已经结束,接下的工作就交给了spring。我们来看看refreshContext(context);
protected void refresh(ApplicationContext applicationContext) {
Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
//调用创建的容器applicationContext中的refresh()方法
((AbstractApplicationContext) applicationContext).refresh();
}
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
/**
* 刷新上下文环境
* 容器状态设置
* 初始化属性设置
* 检查必备属性是否存在
*/
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
/**
* 设置beanFactory序列化id
* 获取BeanFactory;默认实现是DefaultListableBeanFactory,在创建容器的时候创建的
*/
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
/**
* //BeanFactory的预准备工作
* BeanFactory进行一些设置,比如context的类加载器,BeanPostProcessor和XXXAware自动装配等
* 设置忽略的自动装配接口,以及注册一些组件
*/
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
/**
* 提供子类覆盖的额外处理,即子类处理自定义的BeanFactoryPostProcess
*/
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
/**
* 激活各种BeanFactory处理器,包括BeanDefinitionRegistryBeanFactoryPostProcessor和普通的BeanFactoryPostProcessor
* 执行对应的postProcessBeanDefinitionRegistry方法 和 postProcessBeanFactory方法
* 调用BeanDefinitionRegistryBeanFactoryPostProcessor实现向容器内添加bean的定义
* 调用BeanFactoryPostProcessor实现向容器内bean的定义添加属性
*/
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
/**
* 注册拦截Bean创建的Bean处理器,即注册BeanPostProcessor,不是BeanFactoryPostProcessor,注意两者的区别
* 注意,这里仅仅是排序后注册,并不会执行对应的方法,将在bean的实例化时执行对应的方法
*/
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
/**
* 初始化MessageSource组件(做国际化功能;消息绑定,消息解析);
*/
initMessageSource();
// Initialize event multicaster for this context.
/**
* 初始化上下文事件广播器,并放入applicatioEventMulticaster,如ApplicationEventPublisher
*/
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
/**
* 子类重写这个方法,在容器刷新的时候可以自定义逻辑;如创建Tomcat,Jetty等WEB服务器
*/
onRefresh();
// Check for listener beans and register them.
/**
* 注册应用的监听器。就是注册实现了ApplicationListener接口的监听器bean,
* 这些监听器是注册到ApplicationEventMulticaster中的
*/
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
/**
* 初始化所有剩下的非懒加载的单例bean
*/
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
/**
* 完成context的刷新,初始化生命周期处理器,调用LifecycleProcessor的onRefresh()方法,
* 并且发布事件(ContextRefreshedEvent)
*/
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();
}
}
}
}
refresh方法在spring整个源码体系中举足轻重,是实现 ioc 和 aop的关键。
第六步:Spring容器后置处理
protected void afterRefresh(ConfigurableApplicationContext context,
ApplicationArguments args) {
}
扩展接口,设计模式中的模板方法,默认为空实现。如果有自定义需求,可以重写该方法。比如打印一些启动结束log,或者一些其它后置处理。
第七步:发出结束执行的事件
public void started(ConfigurableApplicationContext context) {
for (SpringApplicationRunListener listener : this.listeners) {
//执行EventPublishingRunListener的started方法
listener.started(context);
}
}
@Override
public void started(ConfigurableApplicationContext context) {
//创建ApplicationStartedEvent事件,并且发布事件
//我们看到是执行的ConfigurableApplicationContext这个容器的publishEvent方法,和前面的starting是不同的
context.publishEvent(new ApplicationStartedEvent(this.application, this.args, context));
}
获取EventPublishingRunListener监听器,并执行其started方法,并且将创建的Spring容器传进去了,创建一个ApplicationStartedEvent事件,并执行ConfigurableApplicationContext 的publishEvent方法,也就是说这里是在Spring容器中发布事件,并不是在SpringApplication中发布事件,和前面的starting是不同的,前面的starting是直接向SpringApplication中的11个监听器发布启动事件。
第八步:执行Runners
我们再来看看最后一步callRunners(context, applicationArguments);
private void callRunners(ApplicationContext context, ApplicationArguments args) {
List<Object> runners = new ArrayList<>();
//获取容器中所有的ApplicationRunner的Bean实例
runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
//获取容器中所有的CommandLineRunner的Bean实例
runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
AnnotationAwareOrderComparator.sort(runners);
for (Object runner : new LinkedHashSet<>(runners)) {
if (runner instanceof ApplicationRunner) {
//执行ApplicationRunner的run方法
callRunner((ApplicationRunner) runner, args);
}
if (runner instanceof CommandLineRunner) {
//执行CommandLineRunner的run方法
callRunner((CommandLineRunner) runner, args);
}
}
}
如果是ApplicationRunner的话,则执行如下代码:
private void callRunner(ApplicationRunner runner, ApplicationArguments args) {
try {
(runner).run(args);
}
catch (Exception ex) {
throw new IllegalStateException("Failed to execute ApplicationRunner", ex);
}
}
如果是CommandLineRunner的话,则执行如下代码:
private void callRunner(CommandLineRunner runner, ApplicationArguments args) {
try {
(runner).run(args.getSourceArgs());
}
catch (Exception ex) {
throw new IllegalStateException("Failed to execute CommandLineRunner", ex);
}
}
我们也可以自定义一些ApplicationRunner或者CommandLineRunner,实现其run方法,并注入到Spring容器中,在SpringBoot启动完成后,会执行所有的runner的run方法
至此,SpringApplication大概分析了一遍。
方法步骤:
bean实例化解析
finishBeanFactoryInitialization(beanFactory)方法会实例化所有剩余的非懒加载单例 bean。除了一些内部的 bean、实现了 BeanFactoryPostProcessor 接口的 bean、实现了 BeanPostProcessor 接口的 bean,其他的非懒加载单例 bean 都会在这个方法中被实例化,并且 BeanPostProcessor 的触发也是在这个方法中。
跟踪到AbstractApplicationContext.refresh()方法,找到代码finishBeanFactoryInitialization(beanFactory)查看实现。
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
// 1.初始化此上下文的转换服务
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
// 2.如果beanFactory之前没有注册嵌入值解析器,则注册默认的嵌入值解析器:主要用于注解属性值的解析
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
// 3.初始化LoadTimeWeaverAware Bean实例对象
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
// 4.冻结所有bean定义,注册的bean定义不会被修改或进一步后处理,因为马上要创建 Bean 实例对象了
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
// 5.实例化所有剩余(非懒加载)单例对象
beanFactory.preInstantiateSingletons();
}
继续跟踪到DefaultListableBeanFactory#preInstantiateSingletons
@Override
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
//遍历beanNames,触发所有非懒加载单例bean的初始化
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
//Bean实例:不是抽象类 && 是单例 && 不是懒加载
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
//判断beanName对应的bean是否为FactoryBean
if (isFactoryBean(beanName)) {
//通过getBean(&beanName)拿到的是FactoryBean本身;通过getBean(beanName)拿到的是FactoryBean创建的Bean实例
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
final FactoryBean<?> factory = (FactoryBean<?>) bean;
//判断这个FactoryBean是否希望急切的初始化
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
//如果beanName对应的bean不是FactoryBean,只是普通Bean,通过beanName获取bean实例
getBean(beanName);
}
}
}
else {
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
要理解FactoryBean和Bean的区别
一般情况下,Spring通过反射机制利用bean的class属性指定实现类来实例化 bean。而FactoryBean 是一种特殊的 bean,它是个工厂 bean,可以自己创建 bean 实例,如果一个类实现了FactoryBean 接口,则该类可以自己定义创建实例对象的方法,只需要实现它的 getObject() 方法。
注:很多中间件都利用 FactoryBean 来进行扩展。
引入了几个重要的缓存:
- mergedBeanDefinitions 缓存:beanName -> 合并的 bean 定义。
- beanDefinitionMap 缓存:beanName -> BeanDefinition。
- singletonObjects 缓存:beanName -> 单例 bean 对象。
- earlySingletonObjects 缓存:beanName -> 单例 bean 对象,该缓存存放的是早期单例 bean 对象,可以理解成还未进行属性填充、初始化。
- singletonFactories 缓存:beanName -> ObjectFactory。
- singletonsCurrentlyInCreation 缓存:当前正在创建单例 bean 对象的 beanName 集合。
继续跟踪到AbstractBeanFactory#doGetBean创建bean
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
//解析beanName,主要是解析别名、去掉FactoryBean的前缀“&”
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
//尝试从缓存中获取beanName对应的实例,通过缓存解决循环依赖问题
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//返回beanName对应的实例对象(主要用于FactoryBean的特殊处理,普通Bean会直接返回sharedInstance本身)
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
// scope为prototype非单例的循环依赖校验:如果beanName已经正在创建Bean实例中,而此时我们又要再一次创建beanName的实例,则代表出现了循环依赖,需要抛出异常。
// 例子:如果存在A中有B的属性,B中有A的属性,那么当依赖注入的时候,就会产生当A还未创建完的时候因为对于B的创建再次返回创建A,造成循环依赖
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
//如果parentBeanFactory存在,并且beanName在当前BeanFactory不存在Bean定义,则尝试从parentBeanFactory中获取bean实例
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
if (!typeCheckOnly) {
//如果不是仅仅做类型检测,而是创建bean实例,这里要将beanName放到alreadyCreated缓存
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
//拿到当前bean依赖的bean名称集合,在实例化自己之前,需要先实例化自己依赖的bean,如使用@DependsOn
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance.
if (mbd.isSingleton()) {
//scope为singleton的bean创建(新建了一个ObjectFactory,并且重写了getObject方法,在里面创建bean
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
//返回beanName对应的实例对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
//其它非单例的情况,暂不分析
......
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
return (T) bean;
}
查看DefaultSingletonBeanRegistry#getSingleton
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
//首先检查beanName对应的bean实例是否在缓存中存在,如果已经存在,则直接返回
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
//创建单例前的操作,把bean放入正准备创建的一个Set中singletonsCurrentlyInCreation,如果重复会报异常
//如果存在构造器循环依赖的时候(A(B b),B(C c),C(A a)),会在这点报出异常
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
//执行singletonFactory的getObject方法获取bean实例,就是执行传入方法createBean
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
//创建单例后的操作,在singletonsCurrentlyInCreation中移除
afterSingletonCreation(beanName);
}
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
继承跟踪AbstractAutowireCapableBeanFactory#createBean
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
//验证及准备覆盖的方法(对override属性进行标记及验证)
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
//实例化前的处理,如果有实现InstantiationAwareBeanPostProcessor的BeanPostProcessor可以直接返回真正的bean实例
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
//创建Bean实例(一般真正创建Bean的方法)
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
实例化前的处理,给 InstantiationAwareBeanPostProcessor 一个机会返回代理对象来替代真正的 bean 实例,从而跳过 Spring 默认的实例化过程,达到“短路”效果。会执行 InstantiationAwareBeanPostProcessor 的 postProcessBeforeInstantiation 方法,该方法可以返回 bean 实例的代理,从而跳过 Spring 默认的实例化过程。
查看AbstractAutowireCapableBeanFactory#doCreateBean,这个方法非常重要
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//根据beanName、mbd、args,使用对应的策略创建Bean实例,并返回包装类BeanWrappe
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 这里获取出来的对象是原生对象!!!!!
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
//注意这点,曝光beanName的ObjectFactory,用于解决循环引用。 在开始通过doGetBean取值的时候调用了getSingleton就调用到这个工厂来了
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
//对bean进行属性填充;其中,可能存在依赖于其他bean的属性,则会递归初始化依赖的bean实例
//设置属性,非常重要,比如使用@Autowired注入的值等
populateBean(beanName, mbd, instanceWrapper);
//经过AOP处理,原生对象转换成了代理对象,跟进去
//执行后置处理器,aop就是在这里完成的处理
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
......
return exposedObject;
}
实例化对象createBeanInstance,就是选出一个策略来实例化一个对象, 那有什么策略呢? 这就看程序员是怎么配置的了, 程序员可以配置工厂方法,指定构造方法,或者是程序员没有做出任何干涉,让Spring按自己的方式去实例化
BeanDefinition介绍
-
一个对象在Spring中的描述,RootBeanDefinition是其常见实现
自定义创建Bean
实例化流程
参考:
https://www.cnblogs.com/java-chen-hao/p/11829344.html
网友评论