1.Spring核心之IOC控制反转
1.1 IOC的概念
Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。
IoC 是指在程序开发中,实例的创建不再由调用者管理,而是由 Spring 容器创建。Spring 容器会负责控制程序之间的关系,而不是由程序代码直接控制,因此,控制权由程序代码转移到了 Spring 容器中,控制权发生了反转,这就是 Spring 的 IoC 思想。
1.2 Spring入门案例
1.2.1 创建maven项目
1.2.2 pom.xml文件添加依赖和插件
1.2.3 创建一个实体类
package com.wjx.pojo;
/**
* 实体类球队
*/
public class Team {
private Integer id;
private String name;
private String location;
public Team() {
System.out.println("Team的默认构造方法被调用:id="+id+",name="+name+", location="+location);
}
}
1.2.4 创建Spring的配置文件application.xml
1.2.5 使用Spring容器创建对象
原有写法:new 构造方法();创建对象
配置文件中创建对象
spring的配置文件 :
1、beans: 根标签,spring中java的对象称为为bean
2、spring-beans.xsd 是约束文件(约束XML文件中能编写哪些标签)
创建对象:声明bean,通知spring要创建哪个类的对象
一个bean标签声明一个对象:
id=“自定义的对象名称” ,要求唯一
class=“类的完全限定名” 包名+类名,spring底层是反射机制创建对象,所以必须使用类名
相当于 Team team1=new Team();创建好的对象放入一个集合Map中 例如:
springMap.put(“team1”,new Team());
1.2.6 获取Spring容器
Spring 提供了两种 IoC 容器,分别为 BeanFactory 和 ApplicationContext.
1.2.6.1 BeanFactory
BeanFactory 是基础类型的 IoC 容器,是一个管理 Bean 的工厂,它主要负责初始化各种 Bean,并调用它们的生命周期方法。
BeanFactory 接口有多个实现类,最常见的是 org.Springframework.beans.factory.xml.XmlBeanFactory,它是根据 XML 配置文件中的定义装配 Bean 的。
使用方法:
BeanFactory beanFactory = new XmlBeanFactory(new FileSystemResource(配置文件名));
1.2.6.2 ApplicationContext
ApplicationContext 是 BeanFactory 的子接口,也被称为应用上下文。它不仅提供了 BeanFactory 的 所有功能,还添加了对 i18n(国际化)、资源访问、事件传播等方面的良好支持。
ApplicationContext 接口有两个常用的实现类:
ClassPathXmlApplicationContext——常用
该类从类路径 ClassPath 中寻找指定的 XML 配置文件,找到并装载完成 ApplicationContext 的实例化工作
使用方法:
ApplicationContext applicationContext=new ClassPathXmlApplicationContext(配置文件名称);
FileSystemXmlApplicationContext
使用方法:
ApplicationContext applicationContext = new FileSystemXmlApplicationContext(配置路径);
执行完毕对象还没有创建,而是等到执行getBean()才创建
它与 ClassPathXmlApplicationContext 的区别是:在读取 Spring 的配置文件时,
FileSystemXmlApplicationContext 不再从类路径中读取配置文件,而是通过参数指定配置文件的位置,它可以获取类路径之外的资源,如“D:\application.xml”。
1.2.7 通过上下文对象获取容器中的对象
ApplicationContext applicationContext=new ClassPathXmlApplicationContext(springConfig);
//这里执行完毕容器中的对象都已经创建完成
applicationContext.getBeanDefinitionCount();
返回容器中对象的数量
applicationContext.getBeanDefinitionNames();
返回容器中所有对象的名称数组
根据id,获取对象:
Team team1= (Team) applicationContext.getBean(“team1”);
1.2.8 创建非自定义对象
1.2.9 bean标签的属性
scope=“singleton/prototype” 单例/多例
singleton:默认值,单例:在容器启动的时候就已经创建了单例对象,而且整个容器只有唯一个 的一个该对象
prototype:多例,在使用对象的时候才创建对象,每次使用都创建新的对象
lazy-init=“true/false” 是否延迟创建对象,只针对单例有效
true: 真懒,获取对象的时候才会加载
false:不懒,用不用都加载(默认)
init-method:创建对象之后执行的初始化方法
destroy-method:对象销毁方法,调用容器destroy方法的时候执行
applicationContext.close();//关闭容器,调用指定的销毁方法
1.3 Spring容器创建对象的方式
1.3.1 使用默认的构造方法
1.3.2 使用带参数的构造方法
构造方法:
public Team(Integer id, String name, String location) {
this.id = id;
this.name = name;
this.location = location;
System.out.println("Team - 带参数的构造方法 id="+id+",name="+name+",
location="+location);
}
1.3.3 使用工厂类
工厂类:
配置文件:
1.4 基于XML的DI(通过DI实现IOC)
DI—Dependency Injection,即“依赖注入”:是组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为 了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过 简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资 源来自何处,由谁实现。
IoC 是一个概念,是一种思想,其实现方式多种多样。依赖注入就是其中用的比较多的一种方式
Ioc和DI是同一个概念的不同角度描述。IoC是一种思想,概念,DI是实现它的手段。Spring框架使用依赖注入实现IoC.
Spring 容器是一个超级大工厂,负责创建、管理所有的 Java 对象,这些 Java 对象被称为 Bean。 Spring 容器管理着容器中 Bean 之间的依赖关系,Spring 使用“依赖注入”的方式来管理 Bean 之间的依赖关系。使用 IoC 实现对象之间的解耦和。
1.4.1 注入分类
bean 实例在调用无参构造器创建对象后,就要对 bean 对象的属性进行初始化。初始化是由容器自动完成的,称为注入。
分类:
通过set方法:
set 注入也叫设值注入是指,通过 setter 方法传入被调用者的实例。这种注入方式简单、直
观,因而在 Spring 的依赖注入中大量使用。
通过构造方法:
构造注入是指,在构造调用者实例的同时,完成被调用者的实例化。使用构造器设置依赖关
系。
自动注入:
对于引用类型属性的注入,也可不在配置文件中显示的注入。可以通过为标签设置 autowire 属性值,为引用类型属性进行隐式自动注入(默认是不自动注入引用类型属 性)。根据自动注入判断标准的不同,可以分为两种:
byName:根据名称自动注入
byType: 根据类型自动注入
1、 byName
当配置文件中被调用者 bean 的 id 值与代码中调用者 bean 类的属性名相同时,可使用byName 方式, 让容器自动将被调用者 bean 注入给调用者 bean。容器是通过调用者的 bean类的属性名与配置文件的 被调用者 bean 的 id 进行比较而实现自动注入的。
2、 byType
使用 byType 方式自动注入,要求:配置文件中被调用者 bean 的 class 属性指定的类,要与代码中调用 者 bean 类的某引用类型属性类型同源。即要么相同,要么有 is-a 关系(子类,或是实现类)。但这样 的同源的被调用 bean 只能有一个。多于一个,容器就不知该匹配哪一个了。
实例:
TeamDao类:
TeamService类:
通过set方法:
通过构造方法:
自动注入:
byName:
byType:
1.5 基于注解实现IoC–重要
对于 DI 使用注解,将不再需要在 Spring 配置文件中声明 bean 实例。Spring 中使用注解,需要在原有 Spring 运行环境基础上再做一些改变。
1.5.1 声明Bean的注解 @Component
在类上添加注解@Component表示该类创建对象的权限交给Spring容器。注解的value属性用于指定 bean的id值,value可以省略。
@Component 不指定 value 属性,bean 的 id 是类名的首字母小写。
除此之外,Spring中还提供了其他3个用于创建对象的注解:
@Repository : 用于dao实现类的的注解
@Service: 用户service实现类的注解
@Controller: 用于controller实现类的注解
这三个注解与@Component 都可以创建对象,但这三个注解还有其他的含义,@Service创建业务层对象,业务层对象可以加入事务功能,@Controller 注解创建的对象可以作为处理器接收用户的请求。
@Repository,@Service,@Controller 是对@Component 注解的细化,标注不同层的对象。即持久层对象,业务层对象,控制层对象。
1.5.2 包扫描
需要在 Spring 配置文件中配置组件扫描器,用于在指定的基本包中扫描注解。如果没有扫描,添加的创建对象的注解不生效。
1、使用多个context:component-scan指定不同的包路径
在beans标签中添加命名空间
2、指定 base-package的值使用分隔符
多个包可以依次声明,也可以使用分隔符
分隔符可以使用逗号(,)分号(;)还可以使用空格,不建议使用空格。
3、base-package是指定到父包名
base-package 的值表是基本包,容器启动会扫描包及其子包中的注解,当然也会扫描到子
包下级的子 包。所以 base-package 可以指定一个父包就可以。
但不建议使用顶级的父包,扫描的路径比较多,导致容器启动时间变慢。指定到目标包和合
适的。也就 是注解所在包全路径。
1.5.3 属性注入@Vaule
需要在属性上使用注解@Value,该注解的 value 属性用于指定要注入的值。使用该注解完成属性注入 时,类中无需 setter。当然,若属性有 setter,则也可将value注解加到 setter 上。
1.5.4 byType自动注入@Autowired
需要在引用属性上使用注解@Autowired,该注解默认使用按类型自动装配 Bean 的方式。使用该注解完成属性注入时,类中无需 setter。当然,若属性有 setter,则也可将其加到 setter 上。
1.5.5 byName自动注入@Autowired和@Qualifier
需要在引用属性上联合使用注解@Autowired 与@Qualifier。@Qualifier 的 value 属性用于指定要匹配 的 Bean 的 id 值。类中无需 set 方法,也可加到 set 方法上
@Autowired 还有一个属性 required,默认值为 true,表示当匹配失败后,会终止程序运行。若将其值 设置为 false,则匹配失败,将被忽略,未匹配的属性值为 null。
1.5.6 自动注入@Resource
Spring提供了对 jdk中@Resource注解的支持。@Resource 注解既可以按名称匹配Bean,也可以按类 型匹配 Bean。默认是按名称注入。如果名称没有相符的自动按类型进行装配,使用该注解,要求 JDK 必须是 6 及以上版本。@Resource 可在属性上,也可在 set 方法上。
1、byType注入引用类型属性
@Resource 注解若不带任何参数,采用默认按名称的方式注入,按名称不能注入 bean,则
会按照类型进行 Bean 的匹配注入。
2、byName注入引用类型属性
@Resource 注解指定其 name 属性,则 name 的值即为按照名称进行匹配的 Bean 的 id