目录
1.相关概念
2. 设计IOC容器的两个主要接口
2.1 BeanFactory接口
2.2 ApplicationContext接口
2.3 两个接口的区别【面试题】
3. Bean对象的管理(控制反转)
3.1 基于XML文件管理bean对象
3.2 基于注解方式去管理【重点】
4. 依赖注入(DI)
4.1 setter 方法和构造器注入
4.2 通过注解的方式注入
4.3 set注入和构造器注入的区别
@Resource注解@Autowired注解区别【面试题】
1.相关概念
- 控制反转(IOC):对象的创建权由程序员自身转移到外部容器,这种思想叫做控制反转。
- 依赖注入(DI):容器为应用程序提供运行时所依赖的资源,好做依赖注入。
- Bean对象:IOC容器中创建,管理的对象,称为bean对象。
- 通俗的理解就是:将对象放入容器的思想叫做控制反转;容器为运用程序提供需要的数据这叫做依赖注入;ICO容器中的对象被称为Bean对象。
一张图理解全过程
2. 设计IOC容器的两个主要接口
Spring IoC容器的设计主要是基于BeanFactory和ApplicationContext两个接口实现的。
2.1 BeanFactory接口
BeanFactory是IOC容器的核心接口,他的主要职 责:实例化、定位、配置应用程序中的对象及建立这些对象之间的依赖。
public class BeanFactoryTest {
public static void main(String[] args) {
//初始化Spring容器,加载配置文件
BeanFactory beanFac =
new XmlBeanFactory(new FileSystemResource("D:\\softwaretool
\\eclipseworkspace\\SpringExample\\src\\main
\\resources\\applicationContext.xml"));
//通过容器获取test实例
Student tt = (Student)beanFac.getBean("stu");
System.out.println(tt.getName());;
}
}
上面的代码中,通过BeanFactory的实现类XmlBeanFactory()读取配置文件,然后创建xml中的bean对象,后面通过相应的方法得到该对象并输出。
2.2 ApplicationContext接口
ApplicationContext 是IOC容器的非常重要的一个接口, 它继承了BeanFactory接口的基本功能,同时也继承了容器的高级功能如MessageSouce(国际化 资源接口)、ResourcesLoader(资源加载接口)、ApplicationEventPublisher(应用事件发布 接口)等,在实际的开发应用中我们必然会选择功能强大的ApplicationContext 接口获取资源 信息!
该接口的三个实现类如下
- ClassPathXmlApplicationContext 从类的路径中加载IOC容器配置
- FileSystemXmlApplicationContext 从文件路径加载IOC容器
- XmlWebApplicationContext 从web系统的xml文件中读取配置并加载IOC容器
2.3 两个接口的区别【面试题】
- 加载方式: BeanFactory在启动的时候不会去实例化bean,只有从容器中拿bean的时候才去实例化,应用启动的 时候占用的资源比较少。 ApplicationContext 在启动的时候就把所有的bean默认全部实例化,占用资源,但是可以通过 lazy-init=true来配置bean的延迟加载。
- BeanFactory方法比较旧,初始化容器的时候需要绝对路径查找文件。而ApplicationContext 本身提供3种方式,相对、绝对、web.xml
3. Bean对象的管理(控制反转)
我们希望IOC容器能够帮助我们管理业务bean对象,所以我们必须告诉IOC(配置)容器去管理哪些类,其中有两种方式 。
- 基于XML文件格式 指将bean信息直接配置到Spring核心配置XML中
- 基于注解方式去管理
3.1 基于XML文件管理bean对象
下图所示为xml对bean对象的管理(注入方法,下面介绍)
3.2 基于注解方式去管理【重点】
注解介绍
- @Component 标识一个受Spring管理的基本组件(加载到IOC容器中管理)
- @Repository标识持久层组件类
- @Service 标识业务层组件类
- @Controller 标识控制层组件类
注:@Repository,@Service,@Controller这三个注解包含了@Component,只是为了区分不同的业务层,相当于起了个别名。
如上图所示,使用上面这个注解后,对象自动交给IOC容器管理,及其简单。
4. 依赖注入(DI)
所谓的注入,就是将容器中的值或对象注入给所需的类,Spring提供3种常用方式去注入值,并且可以 注入若干的数据类型,接下来我们学习以下。
- setter 方法注入
- 构造器注入
- 注解的方式注入
4.1 setter 方法和构造器注入
就是在需要用到某个bean对象时,提供该对象的 set 方法,通过该方法将对象传递给使用者。
举例说明:通过注解的方式,将IOC容器中的对象提供给使用者。
1. spring配置文件如下,管理了三个bean对象,分别是demoController,demoController,demoDao
2. 下面demoController类的代码如下,需要的demoService的数据是IOC容器通过set方法注入的。
3.下面demoService类的代码如下,需要的demoDao的数据是IOC容器通过构造器的方式注入的。
demoDao代码如下
执行测试代码
测试结果,说明bean注入成功!
4.2 通过注解的方式注入
有两个注解可以实现注入
@Resource 自动装配(java提供的)
@Autowired 自动装配(spring提供的)
如下图所示的三个类,通过@AutoWired注解将需要的数据自动注入了。如果将该注解换成@Resource,结果是一样的但是这两个注解也有相应的区别。
测试方法如下:
输出结果如下,拿到dao层结果,说明注入成功!
4.3 set注入和构造器注入的区别
setter 注入
- setter 注入需要该Bean包含这些属性的setter方法 与传统的JavaBean的写法更相似,程序开发人员更容易理解、接收。
- 对于复杂的依赖关系,如果采用构造注入,会导致构造器臃肿,难以阅读。Spring在创建Bean实例时,还需要同时实例化依赖的全部实例,会导致性能下降。而使用set注入,则能避免这些问题 。
构造器注入
- 构造注入需要该Bean包含带有这些属性的构造器
- 构造注入可以在构造器中决定依赖关系的注入顺序,优先依赖的优先注入。
- 对于依赖关系无需变化的Bean,构造注入更有用处。,所有的依赖关系全部 在构造器内设定。因此,无需担心后续的代码对依赖关系产生破坏。对组件的调用者而 言,组件内部的依赖关系完全透明,更符合高内聚的原则。
@Resource注解@Autowired注解区别【面试题】
- @Autowired 自动装配可以对成员变量、方法、和构造函数进行标注,来完成自动装配工作, @Autowired会根据类型(byType)进行自动装配 ,使用的时候先去容器中查询注解的类型的bean,如果查询结果为一个,就将该bean装配给 @Autowired指定的数据,如果结果不止一个@Autowired会根据名称匹配(byName),如果查询结果 为空则抛出异常。
- @Resource自动装配首选声明这个注解并不是Spring注解,它是javaEE注解,但Spring默认支持这个注解,@Resource有两个主要的属性, name和type,如果注解时使用name属性,则使用 ByName注入策略,使用type属性时则使用byType自动注入策略,如果都不指定,则通过反射机制默认使用byName注入策略。
- 【简单说】两个都能完成自动装配工 作,@Autowired默认按照byType方式进行bean装配,@Resource默认按照byName方式进行bean装 配,@Resource不是Spring注解,@Resource是JAVAEE注解。
说明:当出现有两个相同的Bean实例时,这种情况一般是一个接口的多个实现类,这时候如果不指定使用哪个实现类就会报错。
下面举例说明,这两个注解遇到这种情况的解决方法。
注:JDK17中java不自带了@Resource注解,需要导入相关依赖