1.概念
控制反转(IoC,Inversion of Control)指将传统上由程序代码直接操控的对象调用权交给容器(对象工厂),通过容器来实现对象的装配和管理。控制反转就是将对象控制权的转移从程序代码本身反转到了外部容器。通过容器实现对象的创建,属性赋值,依赖的管理。
依赖注入(DI,Dependency Injection),指程序运行过程中,若需要调用另一个对象协助时,无须在代码中创建被调用者,而是依赖于外部容器,由外部容器创建后传递给程序。
Spring 容器是一个超级大工厂,负责创建、管理所有的 Java 对象,这些 Java 对象被称为 Bean。Spring 容器管理着容器中 Bean 之间的依赖关系,Spring 使用**“依赖注入**”的方式。来管理 Bean 之间的依赖关系。使用 IoC 实现对象之间的解耦和。 Spring 框架使用依赖注入(DI)实现 IoC。
2.注入分类
bean 实例在调用无参构造器创建对象后,就要对 bean 对象的属性进行初始化。初始化是由容器自动完成的,称为注入。
根据注入方式的不同,常用的有两类:set 注入、构造注入。
2.1.set 注入(掌握)
set 注入也叫设值注入,是指通过 spring调用类的set 方法传入被调用者的实例。这种注入方式简单、直观,因而在 Spring 的依赖注入中大量使用。该注入方法要求在调用类中必须有被调用属性的set方法。构造注入使用 标签
2.1.1简单类型的set注入
2.1.2引用类型的set注入
当指定 bean 的某属性值为另一 bean 的实例时,通过 ref 指定它们间的引用关系。ref的值必须为某 bean 的 id 值。spring调用类的set方法
2.1.3集合属性的set注入
为了演示这些方式,我们在成员中将常见的一些集合都写出来,然后补充其 set 方法
private String[] strs;
private List<String> list;
private Set<String> set;
private Map<String,String> map;
private Properties props;
在配置中也是很简单的,只需要按照下列格式写标签就可以了,可以自己测试一下
<bean id="accountService" class="cn.ideal.service.impl.AccountServiceImpl">
<property name="strs">
<array>
<value>张三</value>
<value>李四</value>
<value>王五</value>
</array>
</property>
<property name="list">
<list>
<value>张三</value>
<value>李四</value>
<value>王五</value>
</list>
</property>
<property name="set">
<set>
<value>张三</value>
<value>李四</value>
<value>王五</value>
</set>
</property>
<property name="map">
<map>
<entry key="name" value="张三"></entry>
<entry key="age" value="21"></entry>
</map>
</property>
<property name="props">
<props>
<prop key="name">张三</prop>
<prop key="age">21</prop>
</props>
</property>
</bean>
2.2. 构造注入(理解)
构造注入是指,在构造调用者实例的同时,完成被调用者的实例化。即,使用构造器设
置依赖关系。该注入方法要求在调用类中必须有调用类的有参构造方法,没有该方法则不能实现依赖注入
构造注入:spring调用类有参数构造方法,在创建对象的同时,在构造方法中给属性赋值。 构造注入使用 标签
标签:一个表示构造方法的一个参数。
标签属性:
name:表示构造方法的形参名
index:表示构造方法的参数的位置,参数从左往右位置是 0 , 1 ,2的顺序
value:构造方法的形参类型是简单类型的,使用value
ref:构造方法的形参类型是引用类型的,使用ref
type:表示构造方法的参数的类型,不过,该属性不要也行,但要注意,若参数类型相同,或之间有包含关系,则需要保证赋值顺序要与构造器中的参数顺序一致。
2.3.引用类型属性自动注入(set)
对于引用类型属性的注入,也可不在配置文件中显示的注入。可以通过为<bean/>
标签设置 autowire 属性值,为引用类型属性进行隐式自动注入(默认是不自动注入引用类型属性)。 **自动注入必须依赖set()方法,也就是说只支持对set注入方式的简写。**根据自动注入判断标准的不同,可以分为两种:
**byName:**根据名称自动注入
byType: 根据类型自动注入
2.3.1.byName 方式自动注入
当配置文件中被调用者 bean 的 id 值与代码中调用者 bean 类的****属性名相同时,可使用byName 方式,让容器自动将被调用者 bean 注入给调用者 bean。容器是通过调用者的 bean类的属性名与配置文件的被调用者 bean 的 id 进行比较而实现自动注入的。
语法:
<bean id="xx" class="yyy" autowire="byName">
简单类型属性赋值
</bean>
2.3.2.byType 方式自动注入
使用 byType 方式自动注入,
**要求:**配置文件中被调用者 bean 的 class 属性指定的类,要与代码中调用者 bean 类的某个引用类型属性类型同源。但这样的同源的被调用 bean 只能有一个。多于一个,容器就不知该匹配哪一个了。
同源就是一类的意思:
1.java类中引用类型的数据类型和bean的class的值是一样的。
2.java类中引用类型的数据类型和bean的class的值父子类关系的。
3.java类中引用类型的数据类型和bean的class的值接口和实现类关系的
语法:
<bean id="xx" class="yyy" autowire="byType">
简单类型属性赋值
</bean>
注意:在byType中, 在xml配置文件中声明bean只能有一个符合条件的,多余一个是错误的
2.4.注解注入
对于 DI 使用注解,将不再需要在 Spring 的xml配置文件中声明 bean 实例。Spring 中使用注解,需要在原有 Spring 运行环境基础上再做一些改变。
需要在 Spring 配置文件中配置组件扫描器(component-scan),用于在指定的基本包中扫描注解。
component-scan工作方式: spring会扫描遍历base-package指定的包,把包中和子包中的所有类,找到类中的注解,按照注解的功能创建对象,或给属性赋值。
指定多个包的三种方式:
- 使用多个 context:component-scan 指定不同的包路径
<context:component-scan base-package="com.ba02" />
<context:component-scan base-package="com.ba03" />
-
使用一个 context:component-scan 指定不同的包路径, base-package 的多个值之间使用分隔符分隔符可以使用逗号(,)分号(;)还可以使用空格,不建议使用空格。
-
base-package 是指定到父包名
base-package 的值表是基本包,容器启动会扫描包及其子包中的注解,当然也会扫描到子包下级的子包。所以 base-package 可以指定一个父包或者最顶级的父包就可以。
<context:component-scan base-package="com" />
但不建议使用顶级的父包,扫描的路径比较多,导致容器启动时间变慢。指定到目标包和合适的。也就是注解所在包全路径。
2.4.1.@Component实现Bean的注解(掌握)
需要在类上使用注解@Component,该注解的 value 属性用于指定该 bean 的 id 值。@Component 可以不指定 value 属性,bean 的 id 是类名的首字母小写。
另外,Spring 还提供了 3 个创建对象的注解:
@Repository 用于对 DAO 实现类进行注解。
@Service 用于对 Service 实现类进行注解。此外,@Service创建的业务层对象可以加入事务功能。
@Controller 用于对 Controller 实现类进行注解。此外,@Controller 注解创建的对象可以作为处理器接收用户的请求。
2.4.2.@Value实现简单类型属性注入(掌握)
需要在属性上使用注解@Value,该注解的 value 属性用于指定要注入的值。使用该注解完成属性注入时,类中无需 setter。当然,若属性有 setter,则也可将其加到 setter 上。
2.4.3.@Autowired实现引用属性byType 自动注入(掌握)
需要在引用属性上使用注解@Autowired,该注解默认使用按类型自动装配 Bean 的方式。
@Autowired 有一个属性 required,默认值为 true,表示当匹配失败后,会终止程序运行。若将其值设置为 false,则匹配失败,将被忽略,未匹配的属性值为 null。
2.4.4.@Autowired +@Qualifier实现引用属性byName 自动注入(掌握)
需要在引用属性上联合使用注解@Autowired 与@Qualifier。@Qualifier 的 value 属性用于指定要匹配的 Bean 的 id 值。
举例:
2.4.5.@Resource 实现引用属性自动注入(掌握)
@Resource 注解既可以按名称匹配Bean,也可以按类型匹配 Bean。默认是按名称注入。使用该注解,要求 JDK 必须是 6 及以上版本。
-
@Resource 注解若不带任何参数,采用默认按名称的方式注入,如果按名称不能注入 bean,则会按照类型进行 Bean 的匹配注入。
-
@Resource 注解指定其 name 属性,则 name 的值即为按照名称进行匹配的 Bean 的 id。
3.注解与XML的对比
优点 | 缺点 | |
---|---|---|
注解 | 方便、直观 、高效(代码少,没有配置文件的书写那么复杂) | 以硬编码的方式写入到 Java 代码中,修改后需要重新编译代码。 |
XML | 配置和代码是分离的、在 xml 中做修改,无需编译代码,只需重启服务器即可将新的配置加载。 | 编写麻烦,效率低,大型项目过于复杂 |
4.项目存在 Spring xml配置文件
在实际应用里,随着应用规模的增加,系统中 Bean 数量也大量增加,导致配置文件变得非常庞大、臃肿。为了避免这种情况的产生,提高配置文件的可读性与可维护性,可以将Spring 配置文件分解成多个配置文件。
包含关系的配置文件:
多个配置文件中有一个主文件,主配置文件将各其它子文件通过<import/>
引入。在 Java代码中只需要使用总配置文件对容器进行初始化即可
主配置文件 : 包含其他的配置文件的,主配置文件一般是不定义对象的。
语法:
例子: