創(chuàng)建bean的過程:
1.使用類的構(gòu)造方法實(shí)例化得到一個(gè)普通對(duì)象(對(duì)于選擇構(gòu)造方法的過程稱為推斷構(gòu)造方法,如果是有一個(gè)構(gòu)造方法直接使用;如果有多個(gè)構(gòu)造方法胳搞,查看是否存在無參的構(gòu)造方法,存在則直接使用;不存在的話逸雹,如果某個(gè)構(gòu)造方法上有@Autowired注解則選擇此構(gòu)造方法营搅,如果都沒有則會(huì)拋出異常,初始化bean失敯鹪摇)
2.得到一個(gè)對(duì)象后转质,spring會(huì)判斷當(dāng)前類中是否存在@Autowired注解了的屬性,把這些屬性進(jìn)行賦值(此過程稱為依賴注入)
3.在依賴注入之后帖世,spring會(huì)判斷當(dāng)前類是否實(shí)現(xiàn)了BeanNameAware接口休蟹,BeanClassLoaderAware接口,BeanFactoryAware接口日矫,如果實(shí)現(xiàn)了赂弓,表示當(dāng)前對(duì)象必須實(shí)現(xiàn)這些接口定義的setBeanName(),setBeanClassLoader(),setBeanFactory()方法哪轿,spring調(diào)用這些方法并且傳入相應(yīng)的參數(shù)(稱為Aware回調(diào))盈魁。
4.在Aware回調(diào)之后,spring需要判斷當(dāng)前對(duì)象的類中是否存在某些方法上使用了@PostConstruct注解窃诉,存在則spring需要調(diào)用這些方法杨耙。(初始化前)
5.之后,spring會(huì)判斷當(dāng)前對(duì)象對(duì)應(yīng)的類是否實(shí)現(xiàn)了InitializingBean,如果實(shí)現(xiàn)了則當(dāng)前對(duì)象必須實(shí)現(xiàn)afterPropertiesSet()方法飘痛,spring就會(huì)調(diào)用當(dāng)前對(duì)象的afterPropertiesSet()方法按脚。(初始化)
6.最后,spring會(huì)判斷當(dāng)前對(duì)象是否需要Aop敦冬,需要的話辅搬,使用動(dòng)態(tài)代理從而生成一個(gè)代理對(duì)象作為Bean;不需要的話脖旱,bean就創(chuàng)建完成堪遂。
擴(kuò)展:
1.為什么同一個(gè)類中兩個(gè)方法a,b都加上了事務(wù)的注解,然后在a中調(diào)用b萌庆,事務(wù)不會(huì)生效溶褪?
因?yàn)槭聞?wù)對(duì)象是一個(gè)代理對(duì)象,當(dāng)代理對(duì)象調(diào)用方法僅調(diào)用a時(shí)践险,事務(wù)是有效的猿妈,此時(shí)使用的是代理對(duì)象;如果調(diào)用了方法a巍虫,再在a中調(diào)用b時(shí)彭则,此時(shí)的對(duì)象已經(jīng)被賦值為普通對(duì)象了,普通對(duì)象調(diào)用b占遥,普通對(duì)象不是事務(wù)的代理對(duì)象俯抖,無法生效。
解決方案:1.把兩個(gè)方法分別寫在不同的類中(經(jīng)常使用)
? ? ? ? ? ? ? ? ? ?2.在當(dāng)前方法中自己注入自己瓦胎,即增加UserService屬性注入芬萍,使用userService.b()方法調(diào)用即可生效尤揣。