ioc就是控制反转,也可以理解为依赖注入。即将一些底层的实现放入到spring-bean容器中。我们使用的话,就不需要太关心具体实现,用的时候,通过构造器注入,setter注入,和注解注入,就可以使用了。
通过set注入。和构造器注入
首先建一个bean.xml包,下面建一个student
public class Student {
private String name;
private String age;
private List list;
//省略get set方法
public Student(String name, String age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" + "name='" + name + '\'' + ", age='" + age + '\'' + ", list=" + list + '}';
}
}
xml配置文件:beanConfig.xml
t1
t2
在建一个实现类
public class HelloService {
private Student student;
public Student getStudent(){
return student;
}
public void setStudent(Student student){
this.student = student;
}
public String gethello(){
return student.toString();
}
}
@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(locations = "classpath:beanConfig.xml")
public class HelloServiceTest extends TestCase {
@Resource
private HelloService helloService;
@Test
public void testGethello() {
System.out.println("helloService.gethello() = " + helloService.gethello());
}
}
xml配置新增
工厂类:
public class FactoryStudent {
private static Map map = new HashMap<>();
static {
map.put(1,new Student("lisi","18"));
map.put(2,new Student("wangwu","19"));
map.put(3,new Student("zhaoliu","20"));
}
public static Student getStudent(int id){
return map.get(id);
}
}
测试使用:
@Test
public void testGethello() {
ApplicationContext context = new ClassPathXmlApplicationContext("beanConfig.xml");
Student factoryStudent = context.getBean("factoryStudent", Student.class);
System.out.println(factoryStudent);
}
打印出来Student{name=‘wangwu’, age=‘19’, list=null}。
@Configuration
public class Animal {
@Bean("dog")
public Dog getDog(){
return new Dog();
}
}
@Component
public class Cat {
private String name;
}
使用的话,通过 @Autowired (ByType注入) @Resource(Byname注入)
以上也涵盖了bean的生命周期。
初始化准备工作,设置启动时间,是否激活标志,初始化属性源配置(property source)。
给beanFactory设置序列号id,并返回beanFactory(bean工厂)
配置bean工厂的上下文属性:比如添加类加载器,后置处理器,并忽略一些自动装配的接口,注册一些属性。
它的作用是:实例化,并调用所有已注册的 bean工厂后置处理器。
调用BeanDefinitionRegistryPostProcessor实现向容器中添加bean的定义。
调用BeanFactoryPostProcessor向bean中添加属性。
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
}
getBeanFactoryPostProcessors:获取所有bean工厂后置处理器。
BeanFactoryPostProcessor可以向容器中注入属性?
如何注入呢?
@Component
public class Teacher {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@Component
public class MyPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition teacher = beanFactory.getBeanDefinition("teacher");
MutablePropertyValues propertyValues = teacher.getPropertyValues();
propertyValues.addPropertyValue("name","wangwu");
}
}
那么teacher这个类已经添加name=wangwu了。
找到BeanPostProcessor的实现,排序后注册进容器中。
初始化国际化文件。(通用语言,比如国际化语言为英语)
初始化应用广播器,如果没有就使用SimpleApplicationEventMulticaster。
创建web容器。
添加容器内事件监听器至事件广播器中
完成此上下文的刷新,调用 LifecycleProcessor(生命周期处理器) 的 onRefresh() 方法,发布ContextRefreshedEvent事件。
完成单例bean的初始化
清除缓存。
重点解析:解决循环依赖。
三级缓存可以解决循环依赖。
3个map+四个方法(解决循环依赖)
一共有两个ApplicationRunner,CommandLineRunner(如果两个order值一样,那么app先执行)。
他们的作用是springboot启动时,需要在启动后执行某些逻辑,那么就需要用启动类加载器了。
定义两个加载器:
@Component
@Order(1)
public class SecondRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("执行app类加载器");
}
}
@Component
@Order(1)
public class FirstRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("\u0018[32m >>> startup first CommandRunner");
}
}
先执行SecondRunner。
从应用上下文中获取SecondRunner和FirstRunner加载器,然后放入到runners数组集合中。排序,最后循环执行run方法。
计时器(用来记录启动时间和当前任务名称)源码中使用了start,和stop方法,可以使用此计时器用于统计时长。
debug断点发现是在doCreateBean—>initializeBean—>applyBeanPostProcessorsBeforeInitialization—>invokeAwareInterfaces
文字描述:aware的实现原理,会先调用bean的初始化之前的后置处理器,也就是一定执行aware接口,也就是实现set方法,并返回当前bean。
根据原理自己写一个aware。
public interface MyAware extends Aware {
void setFlag(Flag flag);
}
@Component
public class Flag {
private boolean isBoolean = true;
//省略get set方法。
}
@Component
public class MyAwareProcessor implements BeanPostProcessor {
private final ConfigurableApplicationContext applicationContext;
public MyAwareProcessor(ConfigurableApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
//为了实现bean的初始化之前的后置处理器方法
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof Aware) {
if (bean instanceof MyAware) {
((MyAware)bean).setFlag((Flag)applicationContext.getBean("flag"));
}
}
return bean;
}
}
测试:
springboot启动打印true。@Component
// @Order(1)
public class ResultRunner implements ApplicationRunner , MyAware {
private Flag fla;
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println(fla.isBoolean());
}
@Override
public void setFlag(Flag flag) {
fla = flag;
}
}
springboot启动打印true。