目录
BeanDefinitionRegistry注册bean定义
BeanDefiinitionScanner扫描哪些真正需要加载的类
ApplicationContext和BeanFactory有什么区别
IOC概念
IOC容器中存放很多JavaBean
回顾
回顾一下我们从刚开始用spring的时候,如何获取一个类的实例的
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
Car car = context.getBean("car",Car.class);
System.out.println(car.getName());
通过配置类MainConfig.class构造了一个容器,然后获取car的实例,打印实例的属性值
我们看下最最重要的方法getBean()
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
this.assertBeanFactoryActive();
return this.getBeanFactory().getBean(name, requiredType);
}
如何获取bean
这里面先获取了BeanFactory,上下文不生产bean,通知beanFactory生产bea(门面模式),这个getBean(),可以获取bean也可以生产bean
BeanFactory,spring顶级核心接口,使用了简单工厂模式,负责生产bean
如何统一交给beanFactory
我们知道,有很多种配置方式来获取bean的实例,比如说注解,或者xml配置,那么到底如何从不同地方读取到的东西统一成一个东西交给beanFactory呢
那就是beanDefinition,bean定义
beanDefinition里面参数
bean的生产方式全都封装在bean定义里面
BeanDefinitionRegistry注册bean定义
BeanDefinitionReader负责读取哪些文件
对配置类或者xml
BeanDefiinitionScanner扫描哪些真正需要加载的类
过程
首先通过BeanDefinitionReader去读取xml文件,比如去扫描哪个包,然后通过BeanDefinitionScanner去扫描那些真正需要加载的类,比如@Component所标注的类,然后找到这些类之后,通过BeanDefinitionRegistry加这些类加载成BeanDefinition,放到beanDefinitionMap里面,beanDefinitionMap交给BeanFactory,然后通过不断地循环,去获取beanDefinition,经过bean的生命周期,将key(beanName)-value(实例)放入到map中
ApplicationContext和BeanFactory有什么区别
ApplicationContext是BeanFactory下面的子类,肯定都有生产bean的能力
BeanFactory只有一个职责就是生产bean,只能进行bean定义,但是ApplicationContext实现了很多类,具备很多功能,可以指定具体扫哪个配置类,管理bean的整个声明周期,事件,国际化,读取资源文件,都为了更好服务类,将类注册成beanDefinition,只有ApplicationContext有read、scanner、registry这个能力
Bean的声明周期
BeanDefinition里面定义了类,通过反射实例化,这个时候是没有属性的,通过@Autowired @value填充属性,然后再初始化,这个时候bean基本成形,然后放到map里面,key为beanName,value是bean的实例,这个map俗称单例池,或者一级缓存
填充属性时,产生循环依赖
循环依赖产生的原因,两个bean对象,互相包含需要注入对方bean对象的属性,这样互相依赖导致循环依赖,当加载a的时候,里面包含b属性,这个时候需要加载b这个实例,加载b的时候,发现需要加载a这个对象,这样就产生了循环依赖
如何解决:spring已经解决了,通过三级缓存(就是三个map)解决的,大体是你创建a的时候,依赖b的属性,开始创建b,创建b的时候,发现依赖a的属性,开始创建a,发现a已经正在创建了就直接出去
实例化
主要有两种方式:反射和工厂,工厂就是new对象然后属性赋值
反射,示例就是用注解生成示例,而工厂,示例就是通过@Bean注解,在方法里面进行属性赋值生成实例
修改beanDefinition
BeanFactoryPostProcessor,实现这个接口的类,可以对bean定义进行修改,大概逻辑就是通过获取beanDefinition,对里面属性进行修改
注册bean定义
每注册一个bean定义就是创建一个bean对象,BeanDefinitionRegistryPostProcessor 总结:
先将类加载成bean定义,先通过BeanDefinitinoReader读取配置类,然后BeanDefinitionScanner扫描符合的类,然后注册成bean定义,然后ApplicationContext可以调用BeanFactoryPostProcessor修改bean定义,还可以调用BeanDefinitionRegistryPostProcessor去注册bean定义,然后通过beanFactory去getBean,getBean可以去创建以及获取bean对象,创建这个过程中包括实例化,填充属性,初始化,中间穿插BeanPostProcessor和各种Aware,然后创建完成之后,放到map里面