1.什么是Spring IOC 容器?
IOC(Inversion of Control)控制反转,将控制权(创建对象和对象之间的依赖关系的权利)交给spring容器。
2.IOC的优点是什么?
接口驱动设计(Interface Driven Design)的好处,可以灵活提供不同的子类实现(其实就是解耦),提高程序的灵活性、可扩展性和可维护性。
IOC模式将耦合代码从程序中移出,放到统一的XML文件中管理。
由IOC容器通过配置文件来管理对象的生命周期、依赖关系等,这样就不用重新修改并编译具体的代码,从而实现组件之间的解耦。
轻量级IOC容器:Pico Container、Avalon、Spring、HiveMind等。
超重量级IOC容器:EJB。
半轻半重IOC容器:JBoss,Jdon等。
IOC的优点:实现组件之间的解耦,提高程序的灵活性和可维护性。
IOC的缺点:
- 创建对象的步骤变复杂了,不直观,当然这是对不习惯这种方式的人来说的。
- 因为使用反射来创建对象,所以在效率上会有些损耗。但相对于程序的灵活性和可维护性来说,这点损耗是微不足道的。
- 缺少IDE重构的支持,如果修改了类名,还需到XML文件中手动修改,这似乎是所有XML方式的缺憾所在。
3.ApplicationContext通常的实现是什么?
spring为ApplicationContext提供的3种实现分别是:ClassPathXmlApplicationContext、FileSystemXmlApplicationContext、XmlWebApplicationContext(是专为Web工程定制的)。
//ClassPathXmlApplicationContext
//第一种方法
AplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");
//第二种
String[] locations = {"bean1.xml", "bean2.xml", "bean3.xml"};
ApplicationContext ctx = new ClassPathXmlApplication(locations);
//注:其中FileSystemXmlApplicationContext和ClassPathXmlApplicationContext与BeanFactory的xml文件定位方式一样是基于路径的。
//FileSystemXmlApplicationContext
//1)
AplicationContext ctx = new FileSystemXmlApplicationContext("bean.xml"); //加载单个配置文件
//2)
S tring[] locations = {"bean1.xml", "bean2.xml", "bean3.xml"};
ApplicationContext ctx = new FileSystemXmlApplicationContext(locations ); //加载多个配置文件
//3)
ApplicationContext ctx =new FileSystemXmlApplicationContext("D:roject/bean.xml");//根据具体路径加载文件
//XmlWebApplicationContext
ServletContext servletContext = request.getSession().getServletContext();
ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(servletContext);
4.Bean 工厂和 Application contexts 有什么区别?
Spring的IoC容器就是一个实现了BeanFactory接口的可实例化类。事实上,Spring提供了两种不同的容器:一种是最基本的BeanFactory,另一种是扩展的ApplicationContext。BeanFactory 仅提供了最基本的依赖注入支持,而 ApplicationContext 则扩展了BeanFactory ,提供了更多的额外功能。
ApplicationContext的初始化和BeanFactory有一个重大的区别:BeanFactory在初始化容器时,并未实例化Bean,直到第一次访问某个Bean时才实例目标Bean;而ApplicationContext则在初始化应用上下文时就实例化所有的单实例的Bean。因此ApplicationContext的初始化时间会比BeanFactory稍长一些。
public class BeanFactoryTest {
public static void main(String[] args) throws Throwable{
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource res = resolver.getResource("classpath:com/baobaotao/beanfactory/beans.xml");
System.out.println(res.getURL());
BeanFactory bf = new XmlBeanFactory(res);
System.out.println("init BeanFactory.");
Car car = bf.getBean("car",Car.class);
System.out.println("car bean is ready for use!");
car.introduce();
}
}
public class XmlApplicationContextTest {
public static void main(String[] args) {
//如果配置文件放置在类路径下,用户可以优先使用ClassPathXmlApplicationContext实现类
ApplicationContext ctx = new ClassPathXmlApplicationContext("com/baobaotao/context/*.xml");
Car car1 = ctx.getBean("car",Car.class);
//如果配置文件放置在文件系统的路径下,则可以优先考虑使用FileSystemXmlApplicationContext实现类
// ctx = new FileSystemXmlApplicationContext("D:/masterSpring/chapter3/src/com/baobaotao/context/*.xml");
// Car car2 = ctx.getBean("car",Car.class);
}
5.什么是Spring的依赖注入?
依赖注入的情况如下:
有两个组件如A和B,A依赖于B,即假设A和B 都是类,且A有一个方法使用到了B,那么如果想要使用B,A必须先要获得组件B的实例引用。这时候如果B是一个接口,虽然我们可以通过该接口的任一实现类来获取组件B的实例引用,但是这样就会使A的可重用性大大降低,无法再采用B的其他实现。
依赖注入,是IOC的一个方面,是个通常的概念,它有多种解释。这概念是说你不用创建对象,而只需要描述它如何被创建。你不在代码里直接组装你的组件和服务,但是要在配置文件里描述哪些组件需要哪些服务,之后一个容器(IOC容器)负责把他们组装起来
6.有哪些不同类型的IOC(依赖注入)方式?
- 编写特定的setter方法:Setter方法注入是容器通过调用无参构造器或无参static工厂 方法实例化bean之后,调用该bean的setter方法,即实现了基于setter的依赖注入
- 采用构造器注入的方式编写特定的构建方法 :构造器依赖注入通过容器触发一个类的构造器来实现的,该类有一系列参数,每个参数代表一个对其他类的依赖
7.哪种依赖注入方式你建议使用,构造器注入,还是 Setter方法注入?
你两种依赖方式都可以使用,构造器注入和Setter方法注入。最好的解决方案是用构造器参数实现强制依赖,setter方法实现可选依赖