1.IoC属于哪种设计模式?
IoC属于工厂设计模式。
2.对Spring IoC和DI的理解,它们有什么区别?
摘自:https://blog.youkuaiyun.com/u013184378/article/details/82953496
(1)IOC:控制反转(Inversion of Control)
- 传统资源查找方式:要求组件向容器发起请求,查找资源作为回应,容器适时返回资源。
- IOC查找方式:容器主动将资源提供给它所管理的组件,组件只需要选择一个合适的方式来接收资源。
- 创建对象实例的控制权由代码控制转移到IOC容器控制(new关键字转移到容器),即在XML文件中控制,控制权转移即所谓的反转,侧重于原理。
(2)DI:依赖注入(Dependency Injection)
- IOC另一种表达方式:组件以一些预先定义好的方式(如setter\getter)接收来自容器的资源注入。
相对于IOC,DI更直接 - 创建对象实例时,为这个对象注入属性值和其他对象实例,侧重于实现。
(3)属性注入
-
set方法注入bean的属性值或依赖的对象
-
name属性:制定bean属性set方法后的属性名
-
value属性:可以使(value)子节点指定属性值
(4)构造器注入
- 通过构造器注入bean属性值或依赖对象,它保证bean实例在实例化后可以使用 。
(5)区别
-
他们是spring核心思想的不同方面的描述
-
依赖注入和控制反转是对同一件事情的不同描述,从某个方面讲,就是他们描述的角度不同
-
依赖注入是从应用程序的角度在描述,应用程序依赖容器创建并注入它所需要的外部资源
-
控制反转是从容器的角度在描述,容器控制应用程序,而容器反向的向应用程序注入应用程序所需要的外部资源
3.简单谈IoC容器的原理
引用:
IOC容器就是具有依赖注入功能的容器,IOC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。应用程序无需直接在代码中new相关的对象,应用程序由IOC容器进行组装。在Spring中BeanFactory是IOC容器的实际代表者。
在Spring Ioc容器的代表就是org.springframework.beans包中的BeanFactory接口,BeanFactory接口提供了IoC容器最基本功能;而org.springframework.context包下的ApplicationContext接口扩展了BeanFactory,还提供了与Spring AOP集成、国际化处理、事件传播及提供不同层次的context实现 (如针对web应用的WebApplicationContext)。简单说, BeanFactory提供了IoC容器最基本功能,而 ApplicationContext 则增加了更多支持企业级功能支持。ApplicationContext完全继承BeanFactory,因而BeanFactory所具有的语义也适用于ApplicationContext。
容器实现一览:
• XmlBeanFactory:BeanFactory实现,提供基本的IoC容器功能,可以从classpath或文件系统等获取资源;File file = new File("fileSystemConfig.xml"); Resource resource = new FileSystemResource(file); BeanFactory beanFactory = new XmlBeanFactory(resource); Resource resource = new ClassPathResource("classpath.xml"); BeanFactory beanFactory = new XmlBeanFactory(resource);
• ClassPathXmlApplicationContext:ApplicationContext实现,从classpath获取配置文件;
BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath.xml");
• FileSystemXmlApplicationContext:ApplicationContext实现,从文件系统获取配置文件。
BeanFactory beanFactory = new FileSystemXmlApplicationContext("fileSystemConfig.xml");
IOC容器工作流程(以xml配置方式举例):
- 准备配置文件:在配置文件中声明Bean定义也就是为Bean配置元数据。
- 由IOC容器进行解析元数据: IOC容器的Bean Reader读取并解析配置文件,根据定义生成BeanDefinition配置元数据对象,IOC容器根据BeanDefinition进行实例化、配置及组装Bean。
- 实例化IOC容器:由客户端实例化容器,获取需要的Bean。
4.bean 的 scope 有几种类型?请详细列举。
引用:
Beans can be defined to be deployed in one of a number of scopes: out of the box, the Spring Framework supports exactly five scopes (of which three are available only if you are using a web-aware ApplicationContext).
Spring容器最初提供了两种bean的scope类型:singleton和prototype,但发布2.0以后,又引入了另外三种scope类型:request、session和global session,这三种只能在web 应用中才可以使用。
- singleton: 在Spring的IoC容器中只存在一个对象实例,所有该对象的引用都共享这个实例。Spring 容器只会创建该bean定义的唯一实例,这个实例会被保存到缓存中,并且对该bean的所有后续请求和引用都将返回该缓存中的对象实例,一般情况下,无状态的bean使用该scope。
- prototype:每次对该bean的请求都会创建一个新的实例,一般情况下,有状态的bean使用该scope。
- request:每次http请求将会有各自的bean实例,类似于prototype。
- session:在一个http session中,一个bean定义对应一个bean实例。
- global session:在一个全局的http session中,一个bean定义对应一个bean实例。典型情况下,仅在使用portlet context的时候有效。
spring的默认scope(bean作用域)是singleton
5. 说说 IoC 中的继承和 Java 继承的区别。
Spring中的Bean继承与Java中的继承截然不同。前者是实例与实例之间的参数的延续,后者则是一般到特殊的细化,前者是对象与对象之间的关系,后者是类与类之间的关系。Spring中的Bean的继承和Java中的Bean的继承有如下区别:
- Sping中的子Bean和父Bean可以是不同类型,但Java中的继承则可保证子类是一种特殊的父类。
- Spring中Bean的继承是实例之间的关系,因此主要表现为参数值的延续;而Java中的继承是类之间的关系,主要表现为方法、属性的延续。
- Spring中子Bean不可作为父Bean使用,不具有多态性;Java中的子类实例完全可以当成父类实例使用。
6. IoC 中 car 对象的配置如下,现在要添加 user 对象,并且将 car 注入到 user 中,正确的配置是?
<bean id="car" class="com.southwind.entity.Car"></bean>
注解的方式注入:
package com.baobaotao.anno;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
//① 定义一个Service的Bean(不需要在XML中定义Bean)
@Service
public class LogonService implements BeanNameAware{
//② 分别注入LogDao及UserDao的Bean(不需要在XML中定义property属性注入)
@Autowired(required=false)
private LogDao logDao;
@Autowired
@Qualifier("userDao")
private UserDao userDao;
public LogDao getLogDao() {
return logDao;
}
public UserDao getUserDao() {
return userDao;
}
public void setBeanName(String beanName) {
System.out.println("beanName:"+beanName);
}
public void initMethod1(){
System.out.println("initMethod1");
}
public void initMethod2(){
System.out.println("initMethod2");
}
}