美文网首页
spring4 IOC的lazy-init源码

spring4 IOC的lazy-init源码

作者: sunpy | 来源:发表于2020-09-04 11:24 被阅读0次

User.java未实例化示例

public class User {
    
    public User() {
        System.out.println("User实例已经创建!");
    }

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
<beans:bean id="user" class="cn.spy.spring.source.code.User" lazy-init="true">
    <beans:property name="name" value="zhangsan"></beans:property>
</beans:bean>

public static void main(String[] args) {
     ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
}

读取bean配置的lazy-init标签

读取lazy-init标签是伴随着读取bean标签是一样的,只是作为bean标签的子节点而已。使用Dom技术读取XML文档(ResouceLoader读取),得到Resouce对象,将Resouce对象转化为Document对象。获取Document中的Element元素对象都封装为BeanDefinition,将BeanDefinition添加到BeanDefinitionMap集合映射中,最终添加到Spring IOC的管理容器BeanFactory(具体是DefaultListBeanFactory)。


读取Element元素中lazy-init属性值
已经读取并加载到BeanFactory

执行lazy-init标签的配置

  1. 完成初始化工作,初始化剩余的单例bean(finishBeanFactoryInitialization)
// 完成初始化工作,初始化剩余的单例bean
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // Initialize conversion service for this context.
    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));
    }

    // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
    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);

    // 冻结bean的定义,注册的bean定义不允许被修改
    beanFactory.freezeConfiguration();

    // 初始化剩余非懒加载方式的单例
    beanFactory.preInstantiateSingletons();
}
  1. 非懒加载方式下的预实例化单例(preInstantiateSingletons)
// 预实例化单例(非懒加载)
@Override
public void preInstantiateSingletons() throws BeansException {
    if (this.logger.isDebugEnabled()) {
        this.logger.debug("Pre-instantiating singletons in " + this);
    }
    List<String> beanNames;
    // 获取所有的Bean名称
    synchronized (this.beanDefinitionMap) {
        // 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.
        beanNames = new ArrayList<String>(this.beanDefinitionNames);
    }
    // 遍历bean,名称
    for (String beanName : beanNames) {
        // 遍历当前bean的父类bean,将父bean与当前bean结合
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
        // bean存在、为单例,不为懒加载才可以预实例化
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
            if (isFactoryBean(beanName)) {
                final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
                boolean isEagerInit;
                if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                    isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
                        @Override
                        public Boolean run() {
                            return ((SmartFactoryBean<?>) factory).isEagerInit();
                        }
                    }, getAccessControlContext());
                }
                else {
                    isEagerInit = (factory instanceof SmartFactoryBean &&
                            ((SmartFactoryBean<?>) factory).isEagerInit());
                }
                if (isEagerInit) {
                    getBean(beanName);
                }
            }
            else {
                getBean(beanName);
            }
        }
    }
}

在preInstantiateSingletons方法中,执行getBean方法实例化的前提必须是单例且非懒加载,所以我们设置了懒加载lazy-init为true,则没有执行实例化操作。而refresh()方法执行完也只是将bean的配置信息添加到了BeanFactory(DefaultListableBeanFactory)进行初始化而已。


解释示例:
所以上面示例中的User.java类就没有实例化,也就不会执行构造方法,而只是将User的bean配置信息加入到BeanFactory而已,等到getBean方法调用才会进行实例化。


相关文章

网友评论

      本文标题:spring4 IOC的lazy-init源码

      本文链接:https://www.haomeiwen.com/subject/llczsktx.html