分析案例前提所参考的例子,Spring Boot中的自定义start pom,SpringBoot学习笔记(3) Spring Boot 运行原理,自动配置
,然后我又看了下nacos的源码,发现原来也都是这做的截图如下:
当然最终的目的我是想知道@Bean helloService实例化过程
/**
* @desc 自定义自动配置加载类:
* 1、编写属性配置类,读取application.properties文件初始化属性
* 2、编写service类。
* 3、编写自定义自动加载配置类
* 4、在配置类中根据HelloServiceProperties提供的参数,并通过ConditionalOnMissingBean判断
* 容器中没有bean时,注入helloService。
*/
@Configuration
@EnableConfigurationProperties(HelloServiceProperties.class)
@ConditionalOnClass(HelloService.class)
@ConditionalOnProperty(prefix = "hello", value = "enabled", matchIfMissing = true)
public class HelloServiceAutoConfiguration {
@Autowired
private HelloServiceProperties helloServiceProperties;
//容器中没有指定的HelloService实例时进行初始化
@Bean
@ConditionalOnMissingBean(HelloService.class)
public HelloService helloService() {
HelloService helloService = new HelloService();
helloService.setMsg(this.helloServiceProperties.getMsg());
return helloService;
}
}
1:首先回顾一下bean创建以及后期处理过程中的主要类的名字和作用,我觉得有两个类需要提前关注下,如下图所示(ctrl+h),
DefaultListableBeanFactory作为默认的bean注册加载的工厂类,继承了AutowireCapableBeanFacotry(提供创建、自动注入、初始化、和后置处理器的作用)
2:调用关系时序图参考 IDEA自动生成方法时序图 -- Sequence Diagram(一款超好用的Idea插件)
当然,时序图有时候也不是万能的。
第一步:
此时启动springboot之后,相继进入AbstractApplicationContext类的refresh()方法,这里我只关注一个finishBeanFactoryInitialization方法,其他的并非本次分析的重点:
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
该refresh()所调用的方法注释翻译:实例化所有剩余的(非延迟初始化)单例,当然到了这一步bean已经全部加载完毕,之后的过程是进行实例化的过程
第二步:
点击进入finishBeanFactoryINitialization方法,此时使用beanFactory就是DefaultListableBeanFactory,准备bean的实例化
/**
* Finish the initialization of this context's bean factory,
* initializing all remaining singleton beans.
*/
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 省略。。。。。
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
}
第三步
分析DefaultListableBeanFactory的preInstantiateSingletons方法,
Ensure that all non-lazy-init singletons are instantiated(确保所有非懒加载的bean都实例化)
@Override
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
// 1:这里的beanDefinitionNames的存储方式这ArrayList
//private volatile List beanDefinitionNames = new ArrayList<>(256);
// 在扩展看下就是 private final Map beanDefinitionMap = new ConcurrentHashMap<>(256);
//volatile 保证了可见性和顺序性,便于判断逻辑的准确实时
List beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 这里我的类并没有实现FactoryBean的接口所以进入else的getBean方法,此处的判断逻辑是这样的:beanType != null && FactoryBean.class.isAssignableFrom(beanType)
// 新的知识点出来了 instanceof, isinstance,isAssignableFrom的区别
// 自身实例或子类实例 instanceof 自身类
// 自身类.class.isInstance(自身实例或子类实例) 返回true
// 自身类.class.isAssignableFrom(自身类或子类.class) 返回true
if (isFactoryBean(beanName)) {
// 省略。。。
}
else {
getBean(beanName);
}
}
}
// 省略。。。。
}
第四步:
查看getBean方法,当然要记住,目前操作都是在DefaultListableBeanFactory,可见,这里多么重要,是bean的存储的地方即beanDefinitionMap,还有创建bean的方法。
之后的过程会进入DefaultListableBeanFactory的父类AbstractBeanFactory执行doGetBean,这里的方法名挺有意思的,我是这么理解的 getBean -表示想要获取bean,doGetBean-那就去获取bean,之后会看到createBean-表示想要创建bean,doCreateBean-真正的创建bean,当然前提条件是DefaultListableBeanFactory里边的三级缓存无数据,这点参考《spring源码分析》对三级缓存的理解,目的是提前暴露bean避免循环依赖,从代码方面可以看出以下缓存的数据结构
/** Cache of singleton objects: bean name to bean instance. */一级缓存
private final Map singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of singleton factories: bean name to ObjectFactory. */ 三级缓存
private final Map> singletonFactories = new HashMap<>(16);
/** Cache of early singleton objects: bean name to bean instance. */二级缓存
private final Map earlySingletonObjects = new HashMap<>(16);
代码角度分析doGetBean的过程:
protected T doGetBean(final String name, @Nullable final Class requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// 缓存检测实例是否提前被暴露,接下来看看里边的缓存是如何处理的
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
//省略。。。
}
else {
//原型模式的bean检测是否存在循环依赖,有的话直接报异常,因为会造成死循环,最终导致程序崩溃
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 省略。。。
try {
// 省略。。。
// Create bean instance.
if (mbd.isSingleton()) {
// 此处对于单例bean的创建,参数是beanNane和接口实现方法
// 最终调用createBean,当然还没完之后还有个doCreate真正去创建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;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// 省略。。。
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// 省略。。。
return (T) bean;
}
分析下第一个获取bean的方法--getSingleton,挺有意思的,对照前面提到的三级缓存结构,大致逻辑是查找一级缓存是否存在实例对象,不存在找二级缓存是否存在实例对象,不存在就再次查找三级缓存是否存在ObjectFactory,如果没有返回空,否则通过beanFactory.getBean获取实例对象,存入二级缓存,同时移除三级缓存对象。同理之后的处理逻辑会从二级缓存提取放入以及缓存,移除二级缓存对象,但是我没搞懂为啥有个二级缓存,可能为了更好的解耦合,见代码:
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
第五步:
现在分析下第二个getSingleton方法,当然我们看到了第二个入参,是个匿名类,一定会调用匿名类的createBean方法,代码如下:
public Object getSingleton(String beanName, ObjectFactory> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
// 省略。。。
// 前置BeanCurrentlyInCreationException判断
beforeSingletonCreation(beanName);
try {
// 匿名类参数的调用,实际上是调用createBean方法,之后会分析createBean方法
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
// 省略。。。
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
// 后置BeanCurrentlyInCreationException判断
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 这块提前看下,就是把bean实例放入一级缓存,之后的调用
// 直接从一级缓存获取
// synchronized (this.singletonObjects) {
// this.singletonObjects.put(beanName, singletonObject);
// this.singletonFactories.remove(beanName);
// this.earlySingletonObjects.remove(beanName);
// this.registeredSingletons.add(beanName);
// }
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
第六步:crreateBean方法,主要做了三个主要的灵魂级别的事情1:创建一个bean实例 ,2:填充bean实例 ,3:执行后置处理器
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) {
// 这里是创建beanInstance的过程,继续跟代码
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");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 这里是丰富化实例,执行属性注入,这里会获取beanPostProcess(getBeanPostProcessors)
// 循环调用得到AutowiredAnnotationBeanPostProcessor,去处理@Autowired注入
// 20200630补注:AutowiredAnnotationBeanPostProcessor类的postProcessProperties方法进行注入
// 当然这里又会持续doGetBean的过程
populateBean(beanName, mbd, instanceWrapper);
// 这里执行后置处理器的过程
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
// 省略。。。
return exposedObject;
}
当然代码继续调用的是doCreateBean方法实现这些过程的。需要额外说明的是spring保证每个bean都要执行beanPostProcess方法,内置了大概是个process方法,也可以自定义,自定义之后,启动refresh的时候,会执行registerBeanPostProcessors方法,大概过程如下:前提已经加载了左右的bean class到beanDefinitionMap容器,之后执行doGetBeanNamesForType方法
private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
List result = new ArrayList<>();
// Check all bean definitions.
for (String beanName : this.beanDefinitionNames) {省略。。。。}
获取所有实现BeanPostProcessor接口的实现类,提取存放到beanPostProcessors里
private final List beanPostProcessors = new CopyOnWriteArrayList<>();
最后在populateBean、exposedObject 时候会执行processor方法,给予实例化的更改实际的机会,大致代码过程
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
当然当执行到ConfigurationBeanBindingPostProcessor的postProcessBeforeInitialization时候会进行@ConfigurationProperties的值反射绑定(bind-->bindDataObject),其绑定的定义值也都是从PropertySource类中获取,说的有点远了,看下PropertySource的结构
public abstract class PropertySource {
protected final Log logger = LogFactory.getLog(getClass());
protected final String name;
protected final T source;
/**
* Create a new {@code PropertySource} with the given name and source object.
*/
public PropertySource(String name, T source) {
Assert.hasText(name, "Property source name must contain at least one character");
Assert.notNull(source, "Property source must not be null");
this.name = name;
this.source = source;
}
其实这个结构存储额所有springboot配置文件的key vale值,可以通过Environment 注入的形式获取,源头都是PropertySource,找到源头是一件非常好玩的一件事情。
第七步:分析createBeanInstance方法,这里挺有意思的,普通方法例如使用@Component,直接进行构造函数实例化,但是本例中使用的是@Configuration @Bean进行实例化的,如下图,所以我猜测spring会给mdb set一个特殊实例化工厂方法,然后执行具体的策略,有兴趣的自己可以在setFacory断点查看,
如我所愿,果真如此,可以看下图,这里边的信息表明@Configuration 真的是将工厂方法策略的元数据信息set到了mdb里边,方便之后的执行操作,具体操作大家应该都能猜到,就是使用的@Bean里边自定义的实例化方法
特殊工厂方法策略实例化代码
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 省略。。。
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// 省略。。。
// 无特殊处理:只需使用无参数构造函数。
return instantiateBean(beanName, mbd);
}
第八步:
protected BeanWrapper instantiateUsingFactoryMethod(
String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
}
继续跟代码,可以看到最终的猜想是否正确,到底使用工厂方法做了什么特殊处理呢?
public BeanWrapper instantiateUsingFactoryMethod(
String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
// 省略。。。。
// 获取工厂
factoryClass = factoryBean.getClass();
// uniqueCandidate是具体@Bean注解的方法Method,之后利用反射执行实例化
bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));
return bw;
利用工厂方法(helloService)进行反射实例化Bean的过程如下
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
@Nullable Object factoryBean, final Method factoryMethod, Object... args) {
try {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction
我的公众号:第一次想认真写写博客,写写生活点滴