springboot实现bean⼿动注⼊操作
1、springboot启动类实现接⼝ApplicationListener<ContextRefreshedEvent>,实现⽅法onApplicationEvent,初始化上下⽂
package test.projectTest;
batis.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 t.ApplicationListener;
import t.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.ApplicationContext());
}
}
2.SpringContextUtil⼯具类初始化ApplicationContext applicationContext
package test.projectTest.util;
import t.ApplicationContext;
/**
* 获取spring容器,以访问容器中定义的其他bean
*/
public class SpringContextUtil{
//spring上下⽂
private static ApplicationContext applicationContext;
/**
* 实现ApplicationContextAware接⼝的回调⽅法,设置上下⽂环境
* @param applicationContext
*/
public static void setApplicationContext(ApplicationContext applicationContext){实例化bean的三种方式
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 = (Bean("dailyDataMapper");
}
}
public static void test(){
dailyDataMapper.selectByPrimaryKey(1);
}
}
补充:springboot中bean的实例化和属性注⼊过程
springboot版本(2.0.4 RELEASE)
⼤致描述springboot中bean的实例化和属性注⼊过程流程
1)在某⼀时刻Spring调⽤了Bean⼯⼚的getBean(beanName)⽅法。beanName可能是simpleController,或者
simpleService,simpleDao,顺序没关系(因为后⾯会有依赖关系的处理)。我们假设simpleController吧
2)getBean⽅法⾸先会调⽤Bean⼯⼚中定义的getSingleton(beanName)⽅法,来判断是否存在该名字
的bean单例,如果存在则返回,⽅法调⽤结束(spring默认是单例,这样可以提⾼效率)
3) 否则,Spring会检查是否存在⽗⼯⼚,如果有则返回,⽅法调⽤结束
4) 否则,Spring会检查bean定义(BeanDefinition实例,⽤来描述Bean结果,component-scan扫描后,就是将beanDefinition实例放⼊Bean⼯⼚,此时还没有被实例化)是否有依赖关系,如果有,执⾏1)步,获取依赖的bean实例
5)否则,Spring会尝试创建这个bean实例,创建实例前,Spring会检查调⽤的构造器,并实例化该Bean,(通过
6) 实例化完成后,Spring会调⽤Bean⼯⼚的populateBean⽅法来填充bean实例的属性,也就是⾃动装配。populateBean⽅法便是调⽤了BeanPostProcessor实例来完成属性元素的⾃动装配⼯作
7)在元素装配过程中,Spring会检查被装配的属性是否存在⾃动装配的其他属性,然后递归调⽤getBean⽅法,知道所有@Autowired的元素都被装配完成。如在装配simpleController中的simpleService属性时,发现SimpleServiceImpl实例中存在@Autowired属性simpleDao,然后调⽤getBean(simpleDao)⽅法,同样会执⾏1)----7)整个过程。所有可以看成⼀个递归过程。
8)装配完成后,Bean⼯⼚会将所有的bean实例都添加到⼯⼚中来。
Bean的实例化
1. 进⼊SpringApplication类中refreshContext()⽅法
2. 进⼊AbstractApplicationContext类中refresh()⽅法,到this.finishBeanFactoryInitialization()⽅法,这个⽅法就是完成beanFactory的实例化
3. 进⼊AbstractApplicationContext类中finishBeanFactoryInitialization()⽅法,到preInstantiateSingletons()
4. 进⼊DefaultListableBeanFactory类中preInstantiateSingletons()⽅法,到getBean()⽅法
5. 进⼊AbstractBeanFactory类中getBean()⽅法,到doGetBean()⽅法
6. 在AbstractBeanFactory类中doGetBean⽅法中,到createBean()⽅法
7. 进⼊AbstractAutowireCapableBeanFactory类中createBean⽅法中,到doCreateBean()⽅法
8. 在AbstractAutowireCapableBeanFactory类中doCreateBean()⽅法中,到createBeanInstance()⽅法,看名字就知道是实例化bean 的