springboot 實現(xiàn)bean手動注入操作
1、springboot啟動類實現(xiàn)接口ApplicationListener<ContextRefreshedEvent>,實現(xiàn)方法onApplicationEvent,初始化上下文
package test.projectTest;
import org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.system.ApplicationPidFileWriter;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import test.projectTest.util.SpringContextUtil;
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class,DataSourceTransactionManagerAutoConfiguration.class, MybatisAutoConfiguration.class})
@SpringBootApplication(scanBasePackages={"test.projectTest"})
public class TestApplication implements ApplicationListener<ContextRefreshedEvent>
{
public static void main( String[] args )
{
SpringApplication application = new SpringApplication(TestApplication.class);
application.addListeners(new ApplicationPidFileWriter());
application.run(args);
System.out.println( "啟動成功" );
}
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
SpringContextUtil.setApplicationContext(event.getApplicationContext());
}
}
2.SpringContextUtil工具類初始化ApplicationContext applicationContext
package test.projectTest.util;
import org.springframework.context.ApplicationContext;
/**
* 獲取spring容器,以訪問容器中定義的其他bean
*/
public class SpringContextUtil{
//spring上下文
private static ApplicationContext applicationContext;
/**
* 實現(xiàn)ApplicationContextAware接口的回調(diào)方法,設(shè)置上下文環(huán)境
* @param applicationContext
*/
public static void setApplicationContext(ApplicationContext applicationContext){
if(null==SpringContextUtil.applicationContext)
SpringContextUtil.applicationContext=applicationContext;
}
public static ApplicationContext getApplicationContext(){
return applicationContext;
}
/**
* 通過name獲取 Bean.
*
* @param name
* @return
*/
public static Object getBean(String name) {
return getApplicationContext().getBean(name);
}
/**
* 通過name獲取 Bean.
*
* @param clazz
* @return
*/
public static <T> T getBean(Class<T> clazz) {
return getApplicationContext().getBean(clazz);
}
/**
* 通過name,以及Clazz返回指定的Bean
*
* @param name
* @param clazz
* @return
*/
public static <T> T getBean(String name, Class<T> clazz) {
return getApplicationContext().getBean(name, clazz);
}
}
3.獲取bean
package test.projectTest.util;
import test.projectTest.mapper.slave.DailyDataMapper;
public class TestUtil{
private static DailyDataMapper dailyDataMapper;
static{//手動注入bean
if(dailyDataMapper==null){
dailyDataMapper = (DailyDataMapper)SpringContextUtil.getBean("dailyDataMapper");
}
}
public static void test(){
dailyDataMapper.selectByPrimaryKey(1);
}
}
補充:springboot中bean的實例化和屬性注入過程
springboot版本(2.0.4 RELEASE)
大致描述springboot中bean的實例化和屬性注入過程流程
1) 在某一時刻Spring調(diào)用了Bean工廠的getBean(beanName)方法。beanName可能是simpleController,或者simpleService,simpleDao,順序沒關(guān)系(因為后面會有依賴關(guān)系的處理)。我們假設(shè)simpleController吧
2)getBean方法首先會調(diào)用Bean工廠中定義的getSingleton(beanName)方法,來判斷是否存在該名字的bean單例,如果存在則返回,方法調(diào)用結(jié)束(spring默認(rèn)是單例,這樣可以提高效率)
3) 否則,Spring會檢查是否存在父工廠,如果有則返回,方法調(diào)用結(jié)束
4) 否則,Spring會檢查bean定義(BeanDefinition實例,用來描述Bean結(jié)果,component-scan掃描后,就是將beanDefinition實例放入Bean工廠,此時還沒有被實例化)是否有依賴關(guān)系,如果有,執(zhí)行1)步,獲取依賴的bean實例
5) 否則,Spring會嘗試創(chuàng)建這個bean實例,創(chuàng)建實例前,Spring會檢查調(diào)用的構(gòu)造器,并實例化該Bean,(通過Constructor.newInstance(args)進(jìn)行實例化)
6) 實例化完成后,Spring會調(diào)用Bean工廠的populateBean方法來填充bean實例的屬性,也就是自動裝配。populateBean方法便是調(diào)用了BeanPostProcessor實例來完成屬性元素的自動裝配工作
7)在元素裝配過程中,Spring會檢查被裝配的屬性是否存在自動裝配的其他屬性,然后遞歸調(diào)用getBean方法,知道所有@Autowired的元素都被裝配完成。如在裝配simpleController中的simpleService屬性時,發(fā)現(xiàn)SimpleServiceImpl實例中存在@Autowired屬性simpleDao,然后調(diào)用getBean(simpleDao)方法,同樣會執(zhí)行1)----7)整個過程。所有可以看成一個遞歸過程。
8)裝配完成后,Bean工廠會將所有的bean實例都添加到工廠中來。
Bean的實例化
1. 進(jìn)入SpringApplication類中refreshContext()方法

2. 進(jìn)入AbstractApplicationContext類中refresh()方法,找到this.finishBeanFactoryInitialization()方法,這個方法就是完成beanFactory的實例化

3. 進(jìn)入AbstractApplicationContext類中finishBeanFactoryInitialization()方法,找到preInstantiateSingletons()

4. 進(jìn)入DefaultListableBeanFactory類中preInstantiateSingletons()方法,找到getBean()方法

5. 進(jìn)入AbstractBeanFactory類中g(shù)etBean()方法,找到doGetBean()方法

6. 在AbstractBeanFactory類中doGetBean方法中,找到createBean()方法

7. 進(jìn)入AbstractAutowireCapableBeanFactory類中createBean方法中,找到doCreateBean()方法

8. 在AbstractAutowireCapableBeanFactory類中doCreateBean()方法中,找到createBeanInstance()方法,看名字就知道是實例化bean的

9. 在AbstractAutowireCapableBeanFactory類createBeanInstance()方法中,找到instantiateBean()方法

10. 在AbstractAutowireCapableBeanFactory類instantiateBean()方法中,找到instantiate()方法

11. 在SimpleInstantiationStrategy類instantiate()方法中,找到instantiateClass()方法

12. 在BeanUtils類instantiateClass()方法中,可知bean的實例化是通過Constructor.newInstance()進(jìn)行實例化

Bean的屬性注入
1. 在AbstractAutowireCapableBeanFactory類doCreateBean()方法中,找到populateBean()方法,從名字可知是用來填充bean的

2. 在AbstractAutowireCapableBeanFactory類中populateBean()方法,找到postProcessPropertyValues()方法

3. 進(jìn)入AutowiredAnnotationBeanPostProcessor類中postProcessPropertyValues()方法中,找到findAutowiringMetadata()方法,在這個方法中,如果屬性中含有@Autowired注解則會遞歸getBean()。沒有然后進(jìn)入inject()方法中

4. 進(jìn)入AutowiredAnnotationBeanPostProcessor類inject方法中,找到resolveDependency()方法,通過這個方法獲取對應(yīng)字段的值

5. 進(jìn)入AutowiredAnnotationBeanPostProcessor類inject方法中,找到field.set(bean, value)方法,通過反射將值設(shè)置到屬性中

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。
相關(guān)文章
springboot調(diào)用支付寶第三方接口(沙箱環(huán)境)
SpringBoot2.6.x 與 Swagger3 兼容問題及解決方法
Springboot+rabbitmq實現(xiàn)延時隊列的兩種方式
java使用CollectionUtils工具類判斷集合是否為空方式
Java中的強(qiáng)引用,軟引用,弱引用,虛引用的作用介紹
Java數(shù)據(jù)結(jié)構(gòu)專題解析之棧和隊列的實現(xiàn)
Java for循環(huán)常見優(yōu)化方法案例詳解

