第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定

Spring Bean注入/單例理解/循環(huán)依賴

標(biāo)簽:
Java

理解循环依赖问题,首先明白spring有四种注入方式。

第一种,SET注入

a类中持有b类的引用,并且a类有b的set方法。在bean中添加<property>标签即可注入。实质上是将b实例化,然后调用set方法注入。

 <bean id="a" class="com.qunar.pojo.StudentA" scope="singleton">
        <property name="studentB" ref="b"></property>
    </bean>
第二种,构造器注入

a类中持有b类的引用,并且a的构造函数参数中有b。实质上就是通过构造函数注入,创建a对象时要把b对象传进去。

  <bean id="a" class="com.qunar.pojo.StudentA">        <constructor-arg index="0" ref="b"></constructor-arg>
    </bean>
第三种,静态工厂

如果有需要静态工厂实例化的类,不能通过静态工厂.方法实现。在bean属性中对应类指向静态工厂,对应方法指向返回实例的方法


第四种,实例工厂

如果工厂不是静态,需要实例化,就实例化对应工厂,设定factory-bean和factory-method进行方法调用。


设定三个实体类,StudentA,B,C代码如下,A持有B,B持有C,C持有A

public class StudentA {
    private StudentB studentB ;    public void setStudentB(StudentB studentB) {        this.studentB = studentB;
    }    public StudentA() {
    }    public StudentA(StudentB studentB) {        this.studentB = studentB;
    }
}

当我通过构造器注入时,会产生BeanCurrentlyInCreationException异常。为什么会出现这种异常,spring如何加载实体?


Spring容器会将每一个正在创建的Bean 标识符放在一个“当前创建Bean池”中,Bean标识符在创建过程中将一直保持在这个池中,因此如果在创建Bean过程中发现自己已经在“当前创建Bean池”里时将抛出BeanCurrentlyInCreationException异常表示循环依赖;而对于创建完毕的Bean将从“当前创建Bean池”中清除掉。

Spring容器先创建单例StudentA,StudentA依赖StudentB,然后将A放在“当前创建Bean池”中,此时创建StudentB,StudentB依赖StudentC ,然后将B放在“当前创建Bean池”中,此时创建StudentC,StudentC又依赖StudentA, 但是,此时Student已经在池中,所以会报错,因为在池中的Bean都是未初始化完的,所以会依赖错误.

解决这个问题,可以用setter注入的方式。



Spring是先将Bean对象实例化之后,再设置对象属性。所以会先调用他的无参构造函数实例化。每个对象存在一个map中。当遇到依赖,就去map中调用对应的单例对象。


一部分源码

另外: 对于“prototype”作用域Bean,Spring容器无法完成依赖注入,因为“prototype”作用域的Bean,Spring容器不进行缓存,因此无法提前暴露一个创建中的Bean。


Spring装配Bean的过程

  1. 实例化;

  2. 设置属性值;

  3. 如果实现了BeanNameAware接口,调用setBeanName设置Bean的ID或者Name;

  4. 如果实现BeanFactoryAware接口,调用setBeanFactory 设置BeanFactory;

  5. 如果实现ApplicationContextAware,调用setApplicationContext设置ApplicationContext

  6. 调用BeanPostProcessor的预先初始化方法;

  7. 调用InitializingBean的afterPropertiesSet()方法;

  8. 调用定制init-method方法;

  9. 调用BeanPostProcessor的后初始化方法;

Spring容器关闭过程

  1. 调用DisposableBean的destroy();

  2. 调用定制的destroy-method方法;



了解了bean默认是单例模式,不由想spring的单例和设计模式单例同一种吗?其实不一样。单例模式是指在一个JVM进程中仅有一个实例,而Spring单例是指一个Spring Bean容器(ApplicationContext)中仅有一个实例。如果有多个Spring容器,可能有多个Bean对象。

spring单例是一种类似注册表实现的方式。利用hashmap,向map中注册和取值,思路类似下面代码

public class Singleton {
    private static Map<String,Singleton> map = new HashMap<String,Singleton>();    static{
        Singleton single = new Singleton();        map.put(single.getClass().getName(), single);
    }    //保护的默认构造子
    protected Singleton(){}    //静态工厂方法,返还此类惟一的实例
    public static Singleton getInstance(String name) {        if(name == null) {
            name = Singleton.class.getName();
        }        if(map.get(name) == null) {            try {                map.put(name, (Singleton) Class.forName(name).newInstance());
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }        return map.get(name);
    }
}

参考文档:
http://blessht.iteye.com/blog/1162131
http://blog.csdn.net/u010644448/article/details/59108799
http://jinnianshilongnian.iteye.com/blog/1415278



作者:icecrea
链接:https://www.jianshu.com/p/ff532b67902a


點(diǎn)擊查看更多內(nèi)容
TA 點(diǎn)贊

若覺得本文不錯(cuò),就分享一下吧!

評(píng)論

作者其他優(yōu)質(zhì)文章

正在加載中
  • 推薦
  • 評(píng)論
  • 收藏
  • 共同學(xué)習(xí),寫下你的評(píng)論
感謝您的支持,我會(huì)繼續(xù)努力的~
掃碼打賞,你說多少就多少
贊賞金額會(huì)直接到老師賬戶
支付方式
打開微信掃一掃,即可進(jìn)行掃碼打賞哦
今天注冊(cè)有機(jī)會(huì)得

100積分直接送

付費(fèi)專欄免費(fèi)學(xué)

大額優(yōu)惠券免費(fèi)領(lǐng)

立即參與 放棄機(jī)會(huì)
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)

舉報(bào)

0/150
提交
取消