Spring 的依赖查找
- 根据Bean名称查找
实时查找
:获得BeanFactory后,直接获取Bean延迟查找
:延迟依赖查找主要用于获取 BeanFactory 后,不马上获取相关的 Bean,不是延迟加载Bean
- 根据Bean类型查找
单个Bean对象
集合Bean对象
-
根据Bean名称+类型查找
-
根据Java注解查找
单个Bean对象
集合Bean对象
Spring 的依赖注入
关键注解:@Autowrite
- 根据Bean名称注入
- 根据Bean类型注入
单个Bean对象
集合Bean对象
- 注入容器内建对象
- 注入非Bean对象
- 注入类型
实时注入
延迟注入
Spring的依赖来源
依赖来源
- 自定义Bean:XML配置或注解定义的Bean
- 容器内建Bean对象:由容器创建的普通的Bean
- 容器内建依赖:通过
AutowireCapableBeanFactory
中的#resolveDependency
方法来注册,不是一个普通Bean,无法通过依赖查找获取
BeanFactory和ApplicationContext,谁才是Spring Ioc的容器?
public static void main(String[] args) {
//假设在Bean.xml中,已经写了配置注入BeanFactory
BeanFactory beanFactoryFromXML = new ClassPathXmlApplicationContext("classpath:/META-INF/bean.xml");
//获取容器里的BeanFactory
BeanFactory beanFactoryFromIoC = beanFactoryFromXML.getBean(BeanFactory.class);
//可以看到 == 时,beanfactoryFromIoC并不等于beanfactoryFromXML
System.out.println(beanFactoryFromIoC == beanFactoryFromXML);
//false
System.out.println(beanFactoryFromXML);
//org.springframework.context.support.ClassPathXmlApplicationContext@574caa3f
//说明依赖查找时的真实容器是ClassPathXmlApplicationContext
}
为什么从容器内获得的BeanFactory
不等于new容器时返回的BeanFactory
?
来看看ApplicationContext
的抽象实现类AbstractApplicationContext
以及实现类GenericApplicationContext
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
//专注于getBean方法,这是依赖查找的主要API
public Object getBean(String name) throws BeansException {
//校验BeanFactory是否在激活状态
this.assertBeanFactoryActive();
//可以看到,ApplicationContext是先获取BeanFactory后,再调用BeanFactory的getBean方法
//那BeanFactory又是从哪里来的?继续看看源代码
return this.getBeanFactory().getBean(name);
}
//getBeanFactory是一个抽象方法,看看子类GenericApplicationContext对其的实现
public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
}
//通用的ApplicationContext实现,不再是抽象类或接口
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
//有一个为DefaultListableBeanFactory类型的属性
private final DefaultListableBeanFactory beanFactory;
//实现了父类的getBeanFactory方法,并且从自身属性返回了一个BeanFactory
public final ConfigurableListableBeanFactory getBeanFactory() {
return this.beanFactory;
}
}
//DefaultListableBeanFactory本身也是BeanFactory的实现者
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
}
- 首先
ApplicationContext
实现了BeanFactory
,因此拥有了BeanFactory
的能力, - 采用了组合的模式,将BeanFactory做为自己的属性
- 当外部调用getBean等属于BeanFactory的能力时,实际是使用了属性中的BeanFactory,有点代理的味道了
其实这么做事很有道理的,ApplicationContext提供更多企业级的能力,专注点在于扩展
而不是容器重实现
ApplicationContext is BeanFactory
,都是Spring的IoC,但是new ClassPathXmlApplicationContext
时的BeanFactory与容器内的BeanFactory,不是同一个对象
ApplicationContext 除了IoC,还提供的功能
- 面向切面(AOP)
- 配置元信息(Configuration Metadata)
- 资源管理(Resources)
- 事件(Evens)
- 国际化(i8n)
- 注解(Annotation)
- Environment抽象(Environment Abstract)
问题:使用Spring容器,选择BeanFactory还是ApplicationContext?
未完待续…
附:BeanFactory体系的最终实现类 - DefaultListableBeanFactory的类图
附:ApplicationContext体系的最终实现类 - AnnotationConfigApplicationContext的类图