doCreateBean
上篇将了实例化之前处理器可能会返回一个对象,如果没有对象,就会进行doCreateBean
真正的创建对象了。这个方法也很复杂,我们慢慢来看。首先会先获取缓存,如果没获取到就创建一个实例,这个实例是BeanWrapper
包装类型的,然后进行处理器处理applyMergedBeanDefinitionPostProcessors
,如果需要解决循环引用就要添加到一个单例工厂里,然后进行属性的填充,初始化,注册销毁回调,最后返回。中间的每一个过程都很复杂,我们慢慢说吧。
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {//获取factoryBean实例缓存
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {//没有即创建实例
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();//获取原始bean
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {//不为空的bean
mbd.resolvedTargetType = beanType;
}
//处理器修改合并bean定义
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
...
}
mbd.postProcessed = true;
}
}
//暴露早期的单例,处理循环引用
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
...
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));//添加一个单例工厂方法
}
//进行初始化
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
...
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException...
}
}
}
}
// Register bean as disposable.
try {//注册可销毁的bean
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
...
}
return exposedObject;
}
createBeanInstance创建bean实例
首先获取类型,然后获取修饰符,只有public
才允许创建,然后在获取自定义的实例提供器,如果有的话直接获取返回,没有的话如果发现有工厂方法名字,就用工厂方法创建,否则的话就要去判断构造函数了,找出合适的构造函数进行自动装配,否则就用默认的构造函数实例化。
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
Class<?> beanClass = resolveBeanClass(mbd, beanName);
//检查是public修饰的
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
//扩展的实例提供器,可以直接从里面获取实例
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
//有工厂方法名的,通过工厂方法获取
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
boolean resolved = false;//标记下,防止重复创建同一个bean
boolean autowireNecessary = false;//是否需要自动装配,构造器有参数的需要
if (args == null) {//无参
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {//有解析的构造器或者工厂方法
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {//有构造参数的或者工厂方法
if (autowireNecessary) {//构造器有参数的
return autowireConstructor(beanName, mbd, null, null);
}
else {//无参的
return instantiateBean(beanName, mbd);
}
}
//从bean后置处理器中为自动装配寻找构造方法
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// 找出最合适的默认构造方法
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
// 最后才用最简单的默认构造方法
return instantiateBean(beanName, mbd);
}
obtainFromSupplier实例提供器
这个主要是我们自己扩展的,我们先来看他里面怎么做的,然后我实战一个就可以啦。
主要就是从给定的提供器里的get()
方法获取bean
实例,然后包装成BeanWrapper
类型,再进行initBeanWrapper
初始化。
protected BeanWrapper obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) {
Object instance;
String outerBean = this.currentlyCreatedBean.get();
this.currentlyCreatedBean.set(beanName);
try {
instance = instanceSupplier.get();
}
finally {
if (outerBean != null) {//不为空还是这是老的
this.currentlyCreatedBean.set(outerBean);
}
else {//为空删除
this.currentlyCreatedBean.remove();
}
}
if (instance == null) {
instance = new NullBean();
}
BeanWrapper bw = new BeanWrapperImpl(instance);
initBeanWrapper(bw);
return bw;
}
InstanceSupplier扩展点实战
InstanceSupplierBeanDefinitionRegistryPostProcessor
先创建后置处理器,里面注册一个bean
定义和实例提供器,提供一个UserDaoImple2
,名字是userDao
要跟MyConfig
中的方法名字一样,可以叫做 处理器添加方式 。
public class InstanceSupplierBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
registry.registerBeanDefinition("userDao",new RootBeanDefinition(UserDao.class, () -> {
System.out.println("UserDao自定义提供器");
return new UserDaoImple2();
}));
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}
UserDaoImple2
public class UserDaoImple2 implements UserDao {
@Override
public void getUser() {
System.out.println("UserDaoImple2 getUser");
}
}
MyConfig
方法名要和实力提供器的bean
名字一样,但是返回的是UserDaoImple
类型的。
@Configuration
public class MyConfig {
@Bean
public UserDao userDao(){
return new UserDaoImple();
}
}
测试
@Test
public void InstanceSupplierTest0() throws Exception {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(MyConfig.class);
applicationContext.addBeanFactoryPostProcessor(new InstanceSupplierBeanDefinitionRegistryPostProcessor());
applicationContext.refresh();
UserDao userDao = (UserDao)applicationContext.getBean("userDao");
System.out.println(userDao);
userDao = (UserDao)applicationContext.getBean("userDao");
System.out.println(userDao);
}
结果
有提供器的:
无提供器的:
这个是怎么回事呢,有了提供器后我们MyConfig
里的方法不起作用啦?是的,其实是bean
定义被覆盖了,还记得前面讲的,配置类处理器会对MyConfig
进行解析,验证,然后加载bean
定义,在加载bean
定义的里面,有个isOverriddenByExistingDefinition
方法,可以判断是否要覆盖现有的bean
定义,因为我们自定义的提供器在最开始的时候就已经注册了bean定义,所以在MyConfig
的userDao
方法加载的时候就会进行判断,看是否要进行覆盖,如果不覆盖就直接返回了,所以我们MyConfig
里的方法信息压根就没注册进bean
定义:
主要的判断代码就是ConfigurationClassBeanDefinitionReader
的isOverriddenByExistingDefinition
,其实是有个判断逻辑,首先是判断已存在的bean
定义是不是和bean
注册方法同一个配置类的重载方法,因为同名嘛,如果是的话就不覆盖,且设置工厂方法不唯一,否则要覆盖,如果不是,就看是不是component scan
扫描进来的bean
定义,是的话要覆盖,如果不是就看是不是内部的,如果是也覆盖,这么说我们可以覆盖spring
内部的处理器啦:
protected boolean isOverriddenByExistingDefinition(BeanMethod beanMethod, String beanName) {
if (!this.registry.containsBeanDefinition(beanName)) {
return false;
}
BeanDefinition existingBeanDef = this.registry.getBeanDefinition(beanName);
//如果是ConfigurationClassBeanDefinition类型的话,且是同一个配置类的重载方法,就保存现有
if (existingBeanDef instanceof ConfigurationClassBeanDefinition) {
ConfigurationClassBeanDefinition ccbd = (ConfigurationClassBeanDefinition) existingBeanDef;
if (ccbd.getMetadata().getClassName().equals(
beanMethod.getConfigurationClass().getMetadata().getClassName())) {
if (ccbd.getFactoryMethodMetadata().getMethodName().equals(ccbd.getFactoryMethodName())) {
ccbd.setNonUniqueFactoryMethodName(ccbd.getFactoryMethodMetadata().getMethodName());//设置工厂方法不唯一,说明有重载
}
//不覆盖
return true;
}
else {
return false;//覆盖
}
}
//如果是component scan, 覆盖现有的
if (existingBeanDef instanceof ScannedGenericBeanDefinition) {
return false;
}
//如果是框架内部的,覆盖现有的
if (existingBeanDef.getRole() > BeanDefinition.ROLE_APPLICATION) {
return false;
}
//不覆盖
return true;
}
我们画个逻辑图:
来看下把spring
内部的默认的配置类处理器改了之后会怎么样吧,如果改了就不会有配置处理器处理了,MyConfig
里的bean
定义也不会有了:
不得不说spring
真的很灵活,扩展性很好,你甚至可以改变内部的处理器,你可以自定义处理器来处理,比如我把初始化的处理器全部覆盖了,现在初始化我说了算,这个扩展性真的很强啊:
这样就被我玩坏了:
最后再提供一种实例提供器的方法, 注册的方式 ,原理一样的:
@Test
public void InstanceSupplierTest0() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(MyConfig.class);
applicationContext.registerBean("userDao",UserDao.class,() -> {
System.out.println("UserDao自定义提供器");
return new UserDaoImple2();
},null);
applicationContext.refresh();
UserDao userDao = (UserDao)applicationContext.getBean("userDao");
System.out.println(userDao);
userDao = (UserDao)applicationContext.getBean("userDao");
System.out.println(userDao);
}
写了那么多,好像又没讲什么,下次继续吧。
好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。
Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。
它的内容包括:
- 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
- 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
- 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
- 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
- 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
- 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
- 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
- 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw
目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:
想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询
同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。