BeanFactory和ApplicationContext谁才是Spring Ioc容器?
BeanFactory 接口提供了能够管理任何类型对象的高级配置机制。ApplicationContext 是BeanFactory 的子接口。ApplicationContext添加了以下特性:
- 更容易与 Spring 的 AOP 特性集成
- 消息资源处理(用于国际化)
- 事件发布。
- 应用层特定的上下文,例如 web 应用程序中使用的 WebApplicationContext。
- public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
- MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
- public interface ListableBeanFactory extends BeanFactory {
简而言之,BeanFactory 提供了配置框架和基本功能,而ApplicationContext 添加了更多特定于企业的功能。
总结:BeanFactory和ApplicationContext可以说都是Spring Ioc容器,在底层实现时,ApplicationContext不止实现了BeanFactory接口,同时还组合了BeanFactory的另一个实现类DefaultListableBeanFactory。
- public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
- public abstract class AbstractXmlApplicationContext extends AbstractRefreshableConfigApplicationContext {
- public abstract class AbstractRefreshableConfigApplicationContext extends AbstractRefreshableApplicationContext
- implements BeanNameAware, InitializingBean {
- public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
- @Nullable
- private Boolean allowBeanDefinitionOverriding;
- @Nullable
- private Boolean allowCircularReferences;
- /** Bean factory for this context. */
- @Nullable
- private DefaultListableBeanFactory beanFactory;
- @Override
- public final ConfigurableListableBeanFactory getBeanFactory() {
- synchronized (this.beanFactoryMonitor) {
- if (this.beanFactory == null) {
- throw new IllegalStateException("BeanFactory not initialized or already closed - " +
- "call 'refresh' before accessing beans via the ApplicationContext");
- }
- return this.beanFactory;
- }
- }
configurableApplicationContext <-ApplicationContext<-BeanFactory
configurableApplicationContext#getBeanFactory()
Spring容器启动的过程中,会将Bean解析成Spring内部的BeanDefinition结构。 不管是是通过xml配置文件的 <Bean> 标签,还是通过注解配置的 @Bean ,还是 @Compontent 标注的类,还是扫描得到的类,它最终都会被解析成一个BeanDefinition对象,最后Bean工厂就会根据这份Bean的定义信息,对bean进行实例化、初始化等等操作。
Bean定义配置注意基于xml文件、properties文件、Java注解以及java Api;
Ioc容器配置注意基于xml文件、Java注解以及Java Api;
外部化属性配置基于Java注解 @Value。
Spring IoC依赖注入
- public class UserRepository {
- /**
- * 自定义bean
- */
- private Collection<User> users;
- /**
- * bean工厂
- * 内建非bean对象
- */
- private BeanFactory beanFactory;
- private ObjectFactory<User> userObjectFactory;
- private ObjectFactory<ApplicationContext> objectFactory;
- public ObjectFactory<ApplicationContext> getObjectFactory() {
- return objectFactory;
- }
- public void setObjectFactory(ObjectFactory<ApplicationContext> objectFactory) {
- this.objectFactory = objectFactory;
- }
- public ObjectFactory<User> getUserObjectFactory() {
- return userObjectFactory;
- }
- public void setUserObjectFactory(ObjectFactory<User> userObjectFactory) {
- this.userObjectFactory = userObjectFactory;
- }
- public Collection<User> getUsers() {
- return users;
- }
- public BeanFactory getBeanFactory() {
- return beanFactory;
- }
- public void setBeanFactory(BeanFactory beanFactory) {
- this.beanFactory = beanFactory;
- }
- public void setUsers(Collection<User> users) {
- this.users = users;
- }
- }
Xml配置信息
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- https://www.springframework.org/schema/beans/spring-beans.xsd">
- <bean id="user" class="org.mango.spring.ioc.overview.domain.User" >
- <property name="id" value="1"/>
- <property name="name" value="mango"/>
- </bean>
- <bean id="superUser" class="org.mango.spring.ioc.overview.domain.SuperUser" parent="user" primary="true">
- <property name="address" value="西安"></property>
- </bean>
- <bean id="objectFactory" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean" >
- <property name="targetBeanName" value="user"></property>
- </bean>
- </beans>
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:util="http://www.springframework.org/schema/util"
- xsi:schemaLocation="
- http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
- <!--通过导入复用 dependency-->
- <import resource="dependency-lookup-context.xml"></import>
- <!--autowire自动注入-->
- <bean id="userRepository" class="org.mango.spring.ioc.overview.repository.UserRepository"
- autowire="byType">
- <!--硬编码-->
- <!-- <property name="users">
- <util:list>
- <ref bean="user"/>
- <ref bean="superUser"/>
- </util:list>
- </property>-->
- </bean>
- </beans>
- //配置xml文件 启动spring 应用上下文
- BeanFactory beanFactory = new ClassPathXmlApplicationContext("META-INF/dependency-injection-context.xml");
- //来源1: 自定义bean
- UserRepository userRepository = (UserRepository) beanFactory.getBean("userRepository");
- //实时注入bean
- userRepository.getUsers().forEach(System.out::println);
- //来源2: 依赖注入 (内建依赖)
- System.out.println(userRepository.getBeanFactory());
- System.out.println(userRepository.getBeanFactory() == beanFactory);
- //延时注入
- ObjectFactory userFactory = userRepository.getUserObjectFactory();
- System.out.println(userFactory.getObject());
- ObjectFactory objectFactory = userRepository.getObjectFactory();
- System.out.println(objectFactory.getObject());
- System.out.println(objectFactory.getObject() == beanFactory);
- //来源三: 容器内建 bean
- Environment environment = beanFactory.getBean(Environment.class);
System.out.println("获取Environment类型的bean" + environment);
System.out.println(userRepository.getBeanFactory() == beanFactory); 输出为false