spring-源码-preInstantiateSingletons

前言

本来想一次性分析整个流程的,想了想还是单小结小结的分析~,主要还是代码来演示结果

所需知识点

  1. 了解 BeanDefinition
  2. 了解 注解 Bean 什么时候转换成 BeanDefinition ,我所说的 Bean 可以简单的理解成 被标注了 @Component的一个类,也就说 这个类什么时候注册成 BeanDefinition

本文演示内容

  1. 工厂 Bean
  2. 合并 Bean
  3. 方法回调

preInstantiateSingletons

  • 单从方法名来看,就是 实例化单例Bean
    public void preInstantiateSingletons() throws BeansException {
        if (logger.isTraceEnabled()) {
            logger.trace("Pre-instantiating singletons in " + this);
        }

        //所有要进行初始的Bean
        List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

        // 对所有Bean进行初始化,除了懒加载
        for (String beanName : beanNames) {
            // 去合并Bean
            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
            //非抽象、单例、懒加载才会进行注册
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                //判断是不是 FactoryBean,简单说是我们这个 Bean 实现了
                if (isFactoryBean(beanName)) {
                    // 是不是 FactoryBean,获取 FactoryBean 的方式就是  前缀+beanName
                    Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                    // 判断是否 FactoryBean
                    if (bean instanceof FactoryBean) {
                        // 强转
                        FactoryBean<?> factory = (FactoryBean<?>) bean;
                        boolean isEagerInit;
                        if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                            isEagerInit = AccessController.doPrivileged(
                                    (PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
                                    getAccessControlContext());
                        } else {
                            // 判断 是不是 这个类的,如果是就去创建 SmartFactoryBean 属于 FactoryBean 子接口,拥有更加细粒度操作原数据的方式,
                            isEagerInit = (factory instanceof SmartFactoryBean &&
                                    ((SmartFactoryBean<?>) factory).isEagerInit());
                        }
                        if (isEagerInit) {
                            getBean(beanName);
                        }
                    }
                } else {
                    //获取具体的Bean
                    getBean(beanName);
                }
            }
        }

        // Trigger post-initialization callback for all applicable beans...

        for (String beanName : beanNames) {
            Object singletonInstance = getSingleton(beanName);
            // 执行所有 单例Bean 的回调,当然Bean 需要实现这个接口~~~
            if (singletonInstance instanceof SmartInitializingSingleton) {
                SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
                if (System.getSecurityManager() != null) {
                    AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                        smartSingleton.afterSingletonsInstantiated();
                        return null;
                    }, getAccessControlContext());
                } else {
                    smartSingleton.afterSingletonsInstantiated();
                }
            }
        }
    }

isFactoryBean

因为当我们的Bean 实现了 这个 FactoryBean 接口后就会走这里,通过 实现 getObject(); 去创建对象

getMergedLocalBeanDefinition

这里是去合并Bean去了,这里其实有两个动作

  1. 将取出来的 BeanDefinition 进行合并
  2. 将BeanDefinition 转换成 RottBeanDefinition 也就说顶级的 Bean ,此处的顶级Bean 指的就是User extends SuperUser,可以认为是是 User,也可以认为是 SuperUser,如果是 User 就代表了已经进行了合并,如果 SuperUser 由于其本身就是顶级类,所以不需要合并,这里会排除掉 Object
  3. 需要注意的是第一次 从 mergedBeanDefinitions 是从 当前的 BeanFactory 中查找
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {

    //从当前 BeanFactory 中的缓存中获取
    RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
    // 不是NUll 并且  没有过期的话,如果过期了或者修改了 会重新去查找
    if (mbd != null && !mbd.stale) {
        //返回当前的
        return mbd;
    }
    // 先去 beanDefinitionMap 中去获取
    BeanDefinition thisBeanDefinition=   getBeanDefinition(beanName);
    // 缓存中未找到,就到 BeanFactory 中寻找
    return getMergedBeanDefinition(beanName, thisBeanDefinition);
}
protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
    throws BeanDefinitionStoreException {
    //传递Name 和BeanDefinition
    return getMergedBeanDefinition(beanName, bd, null);
}
  • 具体的逻辑
    protected RootBeanDefinition getMergedBeanDefinition(
            String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
            throws BeanDefinitionStoreException {

        // 将 mergedBeanDefinitions 防止线程安全,为什么?
        // 虽然 ConcurrentHashMap 是线程安全的,但是下面的业务并不一定是线程安全的,所以要加锁
        synchronized (this.mergedBeanDefinitions) {
            RootBeanDefinition mbd = null;
            RootBeanDefinition previous = null;

            // 这里为空,代表的是 当前的 BeanDefinition 是顶层的 Bean 不存在 嵌套Bean
            if (containingBd == null) {
                // 获取当前Bean,为什么又一次获取了呢?因为如果在多线程操作下 可能 这个Bean已经被修改了,所以重新获取一次
                mbd = this.mergedBeanDefinitions.get(beanName);
            }
            
            //如果缓存中没有,或者过期了,则会重新创建一个
            if (mbd == null || mbd.stale) {
                previous = mbd;
                //如果 父 parentName 为空
                if (bd.getParentName() == null) {
                    // 如果当前类型就是 RootBeanDefinition
                    if (bd instanceof RootBeanDefinition) {
                        // 进行克隆~~~
                        mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
                    } else {
                        // 如果不是就会将 其他 BeanDefinition 转换成 RootBeanDefinition 代表的是当前 BeanDefinition 为顶级 Bean
                        mbd = new RootBeanDefinition(bd);
                    }
                }
                //  如果父 BeanDefinition 不为 空,也就代表了 当前类存在继承,如果不理解这段的话,可以看一下<bean parent=""> bean标签中的 paretn 属性,
                else {
                    // 子bean定义:需要与父bean合并。
                    BeanDefinition pbd;
                    try {
                        String parentBeanName = transformedBeanName(bd.getParentName());
                        // 当前的 BeanName 不是 parentBeanName,会去获取 父BeanDefinition,否则则会去父工厂去获取
                        if (!beanName.equals(parentBeanName)) {
                            // 获取 parent BeanDefinition这里会进行一个递归操作,
                            pbd = getMergedBeanDefinition(parentBeanName);
                        } else {
                            // 如果当前的BeanName 和传递的 parentName 一模一样 则会去父 ParentBeanFactory 查找
                            BeanFactory parent = getParentBeanFactory();
                            // 如果当前是层次 BeanFactory 转换查找,如果不是 抛出异常
                            if (parent instanceof ConfigurableBeanFactory) {
                                pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
                            } else {
                                throw new NoSuchBeanDefinitionException(parentBeanName,
                                        "Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
                                                "': cannot be resolved without a ConfigurableBeanFactory parent");
                            }
                        }
                    } catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
                                "Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
                    }
                    // 进行合并
                    // 进行合并,这里的合并是指将 父级的Bean 合并到子 中,例如  user extends superUser
                    // 也就说讲 super中的 属性 合并到 user 中
                    // Deep copy with overridden values.
                    mbd = new RootBeanDefinition(pbd);
                    mbd.overrideFrom(bd);
                }


                //设置成单例,如果之前没设置的话~~~~
                if (!StringUtils.hasLength(mbd.getScope())) {
                    // 默认为单例
                    mbd.setScope(SCOPE_SINGLETON);
                }

                // A bean contained in a non-singleton bean cannot be a singleton itself.
                // Let's correct this on the fly here, since this might be the result of
                // parent-child merging for the outer bean, in which case the original inner bean
                // definition will not have inherited the merged outer bean's singleton status.
                if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
                    mbd.setScope(containingBd.getScope());
                }

                // Cache the merged bean definition for the time being
                // (it might still get re-merged later on in order to pick up metadata changes)

                // 是否缓存Bean的元数据
                if (containingBd == null && isCacheBeanMetadata()) {
                    // 将当前的 BeanDefinitions 放入到map中,进行缓存
                    this.mergedBeanDefinitions.put(beanName, mbd);
                }
            }
            if (previous != null) {
                copyRelevantMergedBeanDefinitionCaches(previous, mbd);
            }
            return mbd;
        }
    }

说明

其实这一块还是比较绕的涉及到2个知识点

  1. 双 工厂 也就是说当前 工厂 和父类工厂, 当然这里这里的双工厂有点 双亲委派的味道
  2. 还有一个操作就是,会去递归的去获取 父BeanDefinition

getBean

  • 这里暂时不说明,因为这里面的逻辑太复杂了… 后续会有文章进行分析

循环

当所有的单实例 Bean 都创建完成后会重新循环一次 执行 实现了 SmartInitializingSingleton.afterSingletonsInstantiated() 接口的回调,
这里~~本来不想贴代码的…
先说一下这个里的作用:主要是所有单例 bean 创建完成之后,可以在该回调中做一些事情。
需要说明的是 该Demo仅仅是演示了 SmartInitializingSingleton 回调…


@ComponentScan()
public class SmartlnitializingSingletonContext {


    public static void main(String[] args) {
        AnnotationConfigApplicationContext ax = new AnnotationConfigApplicationContext();
        ax.register(SmartlnitializingSingletonContext.class);
        ax.refresh();
    }
}
/**
 * 拥有完整 Bean 生命周期的回调
 */
@Component
@Data
@ToString
class User implements SmartInitializingSingleton {
    @Autowired
    private Adder adder;
    @Override
    public void afterSingletonsInstantiated() {
    }
}
@Data
@ToString
@Component
class Adder {
    private String adder;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'deptServiceImpl': Unsatisfied dependency expressed through field 'baseMapper'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'deptMapper' defined in file [D:\WorkSpace\work13\djd_server\target\classes\com\jiading\djd\mapper\DeptMapper.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: org.apache.ibatis.builder.BuilderException: Error creating document instance. Cause: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 40; 元素内容必须由格式正确的字符数据或标记组成。 at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:643) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE] at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:130) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE] at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1422) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:594) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE] at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:893) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:879) ~[spring-context-5.2.7.RELEASE.jar:5.2.7.RELEASE] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551) ~[spring-context-5.2.7.RELEASE.jar:5.2.7.RELEASE] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:143) ~[spring-boot-2.3.1.RELEASE.jar:2.3.1.RELEASE] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758) [spring-boot-2.3.1.RELEASE.jar:2.3.1.RELEASE] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750) [spring-boot-2.3.1.RELEASE.jar:2.3.1.RELEASE] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) [spring-boot-2.3.1.RELEASE.jar:2.3.1.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) [spring-boot-2.3.1.RELEASE.jar:2.3.1.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1237) [spring-boot-2.3.1.RELEASE.jar:2.3.1.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) [spring-boot-2.3.1.RELEASE.jar:2.3.1.RELEASE] at com.jiading.djd.DjdApplication.main(DjdApplication.java:14) [classes/:na]报错了
最新发布
07-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值