Spring IoC容器
Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想
Ioc 在开发中,无需自行实例对象,而是有 Spring Ioc容器 创建。Spring容器会负责控制程序之间的关系,而不是由代码直接控制,因此,控制权由 Spring容器 接管,控制权发生了反转,是Ioc设计思想
Spring 提供了两种 IoC 容器,分别为 BeanFactory 和 ApplicationContext.
BeanFactory
BeanFactory是一个管理Bean的工厂,根据xml配置文件中的定义Bean进行管理,主要负责初始化各种Bean,并调用他们的生命周期方法
加载xml配置文件,如下所示:(xml文件必须是绝对路径)
BeanFactory beanFactory = new XmlBeanFactory(new FileSystemResource("D:\applicationContext.xml"));
ApplicationContext
ApplicationContext 是 BeanFactory 的子接口,也是 应用上下文。BeanFactory 的所有功能,还添加了对 i18n(国际化)、资源访问、事件传播等方面的良好支持
ApplicationContext 接口有两个常用的实现类
ClassPathXmlApplicationContext
该类从类路径 ClassPath 中寻找指定的 XML 配置文件,找到指定xml文件加载实例化工作,如下所示
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(Spring配
置文件的名称);
FileSystemXmlApplicationContext
该类从指定系统路径的文件 进行寻找指定 XML 配置文件,找到指定xml文件加载实例化工作,如下所示
ApplicationContext applicationContext = new FileSystemXmlApplicationContext(Spring配
置文件的路径和名称);
在读取 Spring 的配置文件时,FileSystemXmlApplicationContext 是通过参数指定配置文件的位置,它可以获取类路径之外的资源
Bean标签
XML 格式配置文件的根元素是 <beans>,该元素包含了多个 <bean> 子元素,每一个 <bean> 子元素定义了一个 Bean,并描述了该 Bean 如何被装配到 Spring 容器中。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<!-- 使用id属性定义person1,其对应的实现类为com.mengma.person1 (类路径及包路径)-->
<bean id="person1" class="com.mengma.person1 " />
<!--使用name属性定义person2,其对应的实现类为com.mengma.domain.Person2 (类路径及包路径) -->
<bean name="Person2" class="com.mengma.domain.Person2"/>
</beans>
bean属性
| 属性名称 | 描述 |
|---|---|
| id | 是一个 Bean 的唯一标识符,Spring 容器对 Bean 的配置和管理都通过该属性完成 |
| name | Spring 容器同样可以通过此属性对容器中的 Bean 进行配置和管理,name 属性中可以为 Bean 指定多个名称,每个名称之间用逗号或分号隔开 |
| class | 该属性指定了 Bean 的具体实现类,它必须是一个完整的类名,使用类的全限定名 |
| scope | 用于设定 Bean 实例的作用域,其属性值有 singleton(单例)、prototype(原型)、request、session 和 global Session。其默认值是 singleton |
| lazy-init | 延迟加载(true/false 默认false)。通过getbean()方法获取对象时才会生效 |
| init-method | 初始化对象方法 |
| destroy-method | 销毁对象方法 |
| list | 用于封装 List 或数组类型的依赖注入 |
| set | 用于封装 Set 类型属性的依赖注入 |
| map | 用于封装 Map 类型属性的依赖注入 |
实例Bean
实例Bean有三种方式,构造器实例化、静态工厂方式实例化、实例工厂方式实例化
创建实体对象
项目 src目录 下
com.Peoplepackage com; public class People { int id; String name; public People() { System.out.println("无参实例"); } public People(int id , String name) { System.out.println("有参实例"); this.id = id; this.name = name; } @Override public String toString() { return "People{" + "id=" + id + ", name='" + name + '\'' + '}'; } }创建工厂
项目 src目录 下com.MyFactorypackage com; public class MyFactory { public MyFactory() { System.out.println("MyFactory--构造!"); } /** * 实例方法 */ public People instanceFun(){ System.out.println("MyFactory---instanceFun"); return new People(001,"成龙"); } /** * 静态方法 */ public static People staticFun(){ System.out.println("MyFactory---staticFun"); return new People(002, "李小龙"); } }创建 Spring配置文件
如果是 Maven项目 ,就放在 resources 下;不是则 自定义位置<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 默认构造--> <bean id="test01" class="com.People" lazy-init="true"/> <!-- 有参构造--> <bean id="test02" class="com.People" lazy-init="true"> <constructor-arg name="id" value="001"/> <constructor-arg name="name" value="嘿嘿嘿"/> </bean> <bean id="test03" class="com.People" lazy-init="true"> <constructor-arg index="0" value="002"/> <constructor-arg index="1" value="啦啦啦"/> </bean> <!-- 工厂方法--> <bean id="test04" class="com.MyFactory" lazy-init="true"/> <bean id="test05" factory-bean="test04" factory-method="instanceFun" lazy-init="true"/> <!-- 工厂方法(静态)--> <bean id="test06" class="com.MyFactory" factory-method="staticFun" lazy-init="true"/> </beans>创建测试类
前提需要引入依赖package com; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MyTest { String createType = "createType.xml"; @Test public void test01(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext(createType); People test01 = (People) applicationContext.getBean("test01"); People test02 = (People) applicationContext.getBean("test02"); People test03 = (People) applicationContext.getBean("test03"); People test05 = (People) applicationContext.getBean("test05"); People test06 = (People) applicationContext.getBean("test06"); System.out.println("============"); System.out.println("test01 : " + test01); System.out.println("test02 : " + test02); System.out.println("test03 : " + test03); System.out.println("test05 : " + test05); System.out.println("test06 : " + test06); } }结果查看
使用 JUnit 测试运行无参实例 有参实例 有参实例 MyFactory--构造! MyFactory---instanceFun 有参实例 MyFactory---staticFun 有参实例 ============ test01 : People{id=0, name='null'} test02 : People{id=1, name='嘿嘿嘿'} test03 : People{id=2, name='啦啦啦'} test05 : People{id=1, name='成龙'} test06 : People{id=2, name='李小龙'}
依赖注入 DI
DI—Dependency Injection,即“依赖注入”。需要通过 简单的配置,而无需任何代码就可指定目标需要的资源
Ioc和DI是同一个概念的不同角度描述。IoC是一种思想;DI是实现它的手段。Spring框架使用依 赖注入实现IoC
| 子元素名称及属性 | 父元素名称 | 说明 |
|---|---|---|
| constructor-arg | bean | 可以使用此元素传入构造参数进行实例化。该元素的 index 属性指定构造参数的序号(从 0 开始),type 属性指定构造参数的类型 |
| property | bean | 用于调用 Bean 实例中的 Set 方法完成属性赋值,从而完成依赖注入。该元素的 name 属性指定 Bean 实例中的相应属性名 |
| entry | map | 用于设置一个键值对。其 key 属性指定字符串类型的键值,ref 或 value 子元素指定其值 |
| 属性 | 值 | 说明 |
| ref | property、constructor-arg、… | 该元素中的 bean 属性用于指定对 Bean 工厂中某个 Bean 实例的引用 |
| value | property、constructor-arg、… | 用于直接指定一个常量值 |
| autowire | byName/byType | 根据 Property 特征进行自动装配 name 或 Type 进行自动装配 |
注入分类
set注入
通过 set 方法传入被调用者的实例。这种注入方式简单、直观,因而在 Spring 的依赖注入中大量使用
public class TeamService {
//注入测试
private TeamDao teamDao;
···
//set注入 (实现TeamDao对象实例)
public void setTeamDao(TeamDao teamDao) {
this.teamDao = teamDao;
}
···
}
构造器注入
在构造调用者实例的同时,完成被调用者的实例化。使用构造器设置依赖关系
public class TeamService {
//注入测试
private TeamDao teamDao;
public TeamService() {}
//构造器注入
public TeamService(TeamDao teamDao) {
this.teamDao = teamDao;
}
···
}
自动注入
可通过 bean标签 设置 autowire 属性值,为引用类型属性进行隐式自动注入(默认是不自动注入引用类型属性)。根据 自动注入判断标准的不同。可以分为两种:
byName:根据名称自动注入
byType: 根据类型自动注入
byName
前提条件:xml配置文件中 bean标签属性 id、name 值 与 调用者类中的属性名 相同,可使用byName方式自动注入依赖实例
.xml配置文件:
<!--id 属性值指定名称--> <bean id="teamDao" class="com.dao.TeamDao"/> <!-- 自动注入--> <!--以Name为注入准则--> <bean id="teamService" class="com.service.TeamService" autowire="byName"/>调用者TeamService类:
public class TeamService { //注入测试 (属性名相同 teamDao ) private TeamDao teamDao; ··· }
byType
前提条件:xml配置文件中 bean标签属性 class值 属性指定的类 与 调用者类中的属性类型相同,可使用byType自动注入依赖实例
.xml配置文件:
<!--class 属性值指定类--> <bean id="teamDao" class="com.dao.TeamDao"/> <!-- 自动注入--> <!--以Name为注入准则--> <bean id="teamService" class="com.service.TeamService" autowire="byType"/>调用者TeamService类:
public class TeamService { //注入测试 (属性类型相同 TeamDao ) private TeamDao teamDao; ··· }
注解装配Bean
在 Spring 中,尽管使用 XML 配置文件可实现 Bean 的装配工作,如果应用中 Bean 的数量较多,会导致 XML 配置文件过于臃肿,从而给维护和升级带来一定的困难,因此 Spring 提供了注解应用,需要在原有的运行环境基础上做些变化,由此减少过多的Bean
@Component
在类上添加上 @Component注解 表示该类实例的对象的权限交给 Spring容器 。注解的value属性用于指定bean的 id值 或 name值 ,但一般情况可省略 value 属性!(该注解指定id是类名的首字母小写)
以下注解与 @Component注解 用法和功能 相同,表达的含义不同!
- @Repository
dao层实现类的注解(持久层)- @Service
service层实现类的注解(业务层)- @Controller
controller层实现类的注解(控制层)
@Value
该 注解 是为指定属性 注入值。该注解用在 类的属性 或 指定set方法上 。
其注解注入 原理 和 set方法 写入是一样,因此 set方法 也可
package com;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class MyUser {
//方式1
@Value("001")
private int id;
@Value("张三")
private String name;
@Value("23")
private int age;
@Value("洛杉矶")
private String locateion;
···
//方式2
@Value("001")
public void setId(int id) {
this.id = id;
}
@Value("张三")
public void setName(String name) {
this.name = name;
}
@Value("23")
public void setAge(int age) {
this.age = age;
}
@Value("洛杉矶")
public void setLocateion(String locateion) {
this.locateion = locateion;
}
···
}
包扫描
需要在 xml配置文件中配置组件扫描器,用于在指定包中扫描的注解。如果未添加扫描,则对象添加的注解 将无法实例化
xml配置文件 添加扫描
beans标签 配置属性
xmlns:context属性:xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation属性(添加值):
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd··· <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> ··· </beans>context:component-scan标签 指定包扫描
分隔符可以使用逗号(,)分号(;)还可以使用空格,不建议使用空格。<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 包扫描 方法1: (包路径 Annotation.dao、Annotation.service、Annotation.controller)--> <context:component-scan base-package="Annotation.dao"/> <context:component-scan base-package="Annotation.service"/> <context:component-scan base-package="Annotation.controller"/> <!-- 包扫描 方法2: (包路径 Annotation.dao、Annotation.service、Annotation.controller)--> <context:component-scan base-package="Annotation.dao;Annotation.service;Annotation.dao"/> </beans>添加对应注解即可
自动注入
自动注入指定对象的前提,需要为该对象添加注解,且 上级包 或 指定类 有扫描到!
@Autowired
用于对 Bean 的 属性变量、属性Set方法 及构造方法进行标注(构造方法应用的前提,参数必须指定的是对应的实例对象),配合对应的注解处理器完成 Bean 的自动配置工作。默认按照 Bean 的类型 进行装配
@Autowired 还有一个属性 required,默认值为 true,表示匹配失败后终止程序运行;若值为 false,则匹配失败后 其属性值为 null
@Qualifier
与 @Autowired 注解配合使用,会将默认的按 Bean类型 装配修改为按 Bean实例队形名称 装配,Bean 的实例名称由 @Qualifier 注解的 value参数 指定
@Resource
该注解 在jdk1.6版本以上 支持使用,Bean属性可指定按照 类型(type) 或 名称(name) 进行自动注入,可在 属性变量、属性Set方法 进行使用