在Spring中实现控制反转的是IoC容器
(1)IoC 不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序。传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试;有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。
(2)其实IoC对编程带来的最大改变不是从代码上,而是从思想上,发生了“主从换位”的变化。应用程序原本是老大,要获取什么资源都是主动出击,但是在IoC/DI思想中,应用程序就变成被动的了,被动的等待IoC容器来创建并注入它所需要的资源了。
(3)IoC很好的体现了面向对象设计法则之一—— 好莱坞法则:“别找我们,我们找你”;即由IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。在spring之前,传统的做法是new来创建对象,有了IOC容器,我们不必主动创建,而是从容器中直接获取。
对于 IoC 来说,最重要的就是容器。因为容器管理着 Bean 的生命周期,控制着 Bean 的依赖注入。spring提供了两种容器类型:Bean Factory和ApplicationContext。
一、 BeanFactory和ApplicationContext的关系:
Spring容器是生成Bean实例的工厂,并管理容器中的Bean。在基于Spring的Java EE应用中,所有的组件都被当成Bean处理,包括数据源,Hibernate的SessionFactory、事务管理器等。Spring的两大核心接口,而ApplicationContext是BeanFactory的子接口。它们都可以当做Spring的容器。
1、继承关系
Bean创建的主要逻辑和功能都被封装在BeanFactory中,ApplicationContext不仅继承了BeanFactory,而且ApplicationContext内部还维护着BeanFactory的引用,所以,ApplicationContext与BeanFactory既有继承关系,又有融合关系。
ApplicationContext除了继承了BeanFactory外,还继承了ApplicationEventPublisher(事件发布器)、ResouresPatternResolver(资源解析器)、MessageSource(消息资源)等。但是ApplicationContext的核心功能还是BeanFactory。
BeanFactory通常以编程的方式被创建,ApplicationContext还能以声明的方式创建,如使用ContextLoader。
2、作用不同
2.1、BeanFactory
是Spring的早期接口,称为Spring的Bean工厂,这是最简单的容器,只能提供基本的DI功能,包含了各种Bean的定义、加载、实例化,依赖注入和生命周期管理;
2.2、ApplicationContext
ApplicationContext(应用上下文),是后期更高级接口,称之为Spring容器,它能提供更多企业级的服务,例如解析配置文本信息等等,这也是ApplicationContext实例对象最常见的应用场景。BeanFactory的API更偏向底层,ApplicationContext的API大多数是对这些底层API的封装;
ApplicationContext接口作为BeanFactory的子类,除了提供BeanFactory所具有的功能外,还提供了更完整的框架功能:
(1)继承MessageSource,因此支持国际化。
(2)资源文件访问,如URL和文件(ResourceLoader)。
(3)载入多个(有继承关系)上下文(即同时加载多个配置文件) ,使得每一个上下文都专注于一个特定的层次,比如应用的web层。
(4)提供在监听器中注册bean的事件。
3、Bean的初始化时机不同
(1)BeanFactroy采用的是延迟加载形式来注入Bean的,只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化。这样,我们就不能提前发现一些存在的Spring的配置问题。如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次使用调用getBean方法才会抛出异常。
(2)ApplicationContext,它是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误,这样有利于检查所依赖属性是否注入。
ApplicationContext启动后预载入所有的单实例Bean,所以在运行的时候速度比较快,因为它们已经创建好了。相对于BeanFactory,ApplicationContext 唯一的不足是占用内存空间,当应用程序配置Bean较多时,程序启动较慢。
4、其他比较
BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但两者之间的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册。
二、BeanFactory:常见用法:xml和注解:
1、xml:
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
public class Main {
public static void main(String[] args) {
// 创建BeanFactory容器并加载XML配置文件
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
// 从容器中获取Bean实例
UserService userService = (UserService) beanFactory.getBean("userService");
OrderService orderService = (OrderService) beanFactory.getBean("orderService");
// 使用Bean
userService.sayHello();
orderService.placeOrder();
}
}
2、注解:
public class User {
private String name;
public User() {}
public User(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public void sayHello() {
System.out.println("Hello, " + name + "!");
}
}
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args) {
// 创建BeanFactory容器并扫描包
BeanFactory beanFactory = new AnnotationConfigApplicationContext("com.example");
// 从容器中获取Bean实例
User user = beanFactory.getBean(User.class);
// 使用Bean
user.sayHello();
}
}