1. Spring IOC基础
Spring框架IOC实现 | JavaSE应用下该IOC容器启动方式 | JavaWeb应用下该IOC容器启动方式 |
---|---|---|
纯xml | new ClassPathXmlApplicationContext("beans.xml"); 或者new FileSystemXmlApplicationContext("c:/beans.xml"); |
ContextLoaderListener(监听器去加载xml) |
xml+注解 | new ClassPathXmlApplicationContext("beans.xml"); 或者new FileSystemXmlApplicationContext("c:/beans.xml"); |
ContextLoaderListener(监听器去加载xml) |
纯注解模式 | new AnnotationConfigApplicationContext("SpringConfig.class"); | ContextLoaderListener(监听器去加载注解配置类) |
1.1 BeanFactory与ApplicationContext区别
BeanFactory是Spring框架中IoC容器的顶层接⼝,它只是⽤来定义⼀些基础功能,定义⼀些基础规范,⽽ApplicationContext是它的⼀个⼦接⼝,所以ApplicationContext是具备BeanFactory提供的全部功能的。
通常,我们称BeanFactory为SpringIOC的基础容器,ApplicationContext是容器的⾼级接⼝,⽐BeanFactory要拥有更多的功能,⽐如说国际化⽀持和资源访问(xml,java配置类)等等
启动容器的方式
- Java环境下启动IOC容器
- ClassPathXmlApplicationContext:从类的根路径下加载配置文件(推荐使用)
- FileSystemXmlApplicationContext:从磁盘路径下加载配置文件
- AnnotationConfigApplicationContext:纯注解模式下启动Spring容器
- Web环境下启动IOC容器
- 从xml启动容器
Archetype Created Web Application
contextConfigLocation
classpath:applicationContext.xml
org.springframework.web.context.ContextLoaderListener
2. 从配置类加载启动容器
Archetype Created Web Application
contextClass
org.springframework.web.context.support.AnnotationConfigWebAppli
cationContext
contextConfigLocation
com.lagou.edu.SpringConfig
org.springframework.web.context.ContextLoaderListener
1.2 纯xml形式
- xml文件头
- 实例化bean的三种方式
方式一:使用无参构造函数
在默认情况下,它会通过反射调用无参构造函数来创建对象。如果 类中没有无参构造函数,将创建失败。
方式二:使用静态方法创建
在实际开发中,我们使⽤的对象有些时候并不是直接通过构造函数就可以创建出来的,它可能在创建的过程 中会做很多额外的操作。此时会提供⼀个创建对象的⽅法,恰好这个⽅法是static修饰的⽅法,即是此种情况。
例如,我们在做Jdbc操作时,会⽤到java.sql.Connection接⼝的实现类,如果是mysql数据库,那么⽤的就是JDBC4Connection,但是我们不会去写 JDBC4Connection connection = new JDBC4Connection() ,因为我们要注册驱动,还要提供URL和凭证信息,⽤ DriverManager.getConnection ⽅法来获取连接。
那么在实际开发中,尤其早期的项⽬没有使⽤Spring框架来管理对象的创建,但是在设计时使⽤了⼯⼚模式解耦,那么当接⼊spring之后,⼯⼚类创建对象就具有和上述例⼦相同特征,即可采⽤此种⽅式配置。
方式三:使用实例化方法创建
此种方式和上⾯静态方法创建其实类似,区别是用于获取对象的方法不再是static修饰的了,而是类中的⼀个普通方法,且需要配置工厂bean,并在业务bean中配置factory-bean,factory-method属性。
在早期开发的项⽬中,工厂类中的方法有可能是静态的,也有可能是非静态方法,当是非静态方法时,即可采用下⾯的配置方式:
- Bean的X以及生命周期
在spring框架管理Bean对象的创建时,Bean对象默认都是单例的,但是它⽀持配置的⽅式改变作⽤范围。作⽤范围如下。
Scope | Description |
---|---|
singleton | 单例模式,使用 singleton 定义的 Bean 在 Spring 容器中只有一个实例,这也是 Bean 默认的作用域。 |
prototype | 原型模式,每次通过 Spring 容器获取 prototype 定义的 Bean 时,容器都将创建一个新的 Bean 实例。 |
request | 在一次 HTTP 请求中,容器会返回该 Bean 的同一个实例。而对不同的 HTTP 请求,会返回不同的实例,该作用域仅在当前 HTTP Request 内有效。。 |
seesion | 在一次 HTTP Session 中,容器会返回该 Bean 的同一个实例。而对不同的 HTTP 请求,会返回不同的实例,该作用域仅在当前 HTTP Session 内有效。 |
application | ServletContext的生命周期。仅在可感知web的Spring应用程序上下文中有效。 |
websocket | websocket的生命周期。仅在可感知web的Spring应用程序上下文中有效 |
在上图中提供的这些选项中,我们实际开发中⽤到最多的作⽤范围就是singleton(单例模式)和prototype(原型模式,也叫多例模式)。配置⽅式参考下⾯的代码:
- 不同作用范围的生命周期
- 单例模式
对象出生:当创建容器时,对象就被创建
对象存活:只要容器在,对象一直活着
对象死亡:当销毁容器时,对象就被销毁了
一句话总结: 单例的bean对象生命周期和容器相同 - 多例模式
对象出生:当使用对象时,创建新的对象实例
对象存活:只要对象在使用中,对象一直活着
对象死亡:当对象长时间不用时,被java的垃圾回收哦器回收了
一句话总结: 多例模式的bean对象,Spring框架只负责创建不负责销毁。
- Bean标签属性
在基于xml的IOC配置中,bean标签是最基础的标签。它表示了IOC容器中的一个对象。换句话说,如果一个对象想让Spring管理,在xml的配置中都需要使用此标签配置,Bean标签的属性如下:- id属性:用于给bean提供一个唯一标识。在一个标签内部,标识必须唯一。
- class属性:用于指定创建Bean对象的全限定类名。
- name属性:用于给bean 提供一个或多个名称,多个名称用空格分隔。
- factory-bean属性:用于指定创建当前bean对象的工厂bean的唯一标识。当指定了此属性之后,class属性失效。
- factory-method属性:用于指定创建当前bean对象的工厂方法,如配合factory-bean使用,则class属性失效(实例化方法创建);如配合class属性使用,则方法必须是static的(静态方法创建)。
- scope属性:用于指定bean对象的作用范围。通常情况下就是singleton,当需要用到多例模式时,可以配置为prototype。
- init-method属性:用于指定bean对象的初始化方法,此方法会在bean对象装配后调用。必须是无参方法。
- destory-method属性:用于指定bean对象的销毁方法,此方法会在bean对象销毁前执行。他只能为scope是singleton时起作用。
- DI依赖注入的xml配置
- 依赖注入分类
- 按照注入的方式分类
构造函数注入:顾名思义,就是利用带参构造函数实现对类成员的数据赋值。
set方法注入:它是通过类成员的set方法实现数据的注入。 - 按照注入的数据类型分类
基本类型和String:注入的数据类型是基本类型或者是字符串类型的数据。
其他Bean类型:注入的数据类型是对象类型,称为其他的Bean的原因是,这个对象要求出现在IOC容器中的,那么针对当前Bean来说,就是其他Bean了。
复杂类型(集合类型):注入的数据类型是Array,List,Set,Map,Properties中的一种类型。
- 按照注入的方式分类
- 依赖注入的配置实现之构造函数注入
顾名思义,就是利用构造函数实现对类成员的赋值。它的使用要求是,类中提供的构造函数参数个数必须是配置的参数个数一致,且数据类型匹配。同时需要注意的是,当没有无参构造时,则必须提供构造函数参数的注入,否则Spring框架会报错。
在使用构造函数注入时,涉及到的标签是constructor-arg,该标签有如下属性:
name:用于给构造函数中指定名称的参数赋值。
index:用于给构造函数指定索引位置的参数赋值。
value:用于指定基本类型或者String类型的数据。
ref:用于指定其他Bean类型的数据。写的是其他bean的唯一标识。 - 依赖注入的配置实现之set方法注入
顾名思义,就是利用字段的set方法实现赋值的注入方式。
在使用set方法注入时,需要使用的标签是property,该标签有如下属性:
name:指定注入时调用的set方法名称。(注:不包含set这三个字母)
value:指定注入的数据,它支持基本类型和String类型。
ref:指定注入的数据,它指定其他bean类型。写的是其他的bean的唯一标识。 -
复杂数据类型注入
首先说明一下复杂属性类型,它指的是集合类型数据。集合分两类某一类是List结构(数组结构),一类是Map接口(键值对)。
接下来就是注入的方式的选择,只能在构造函数和set方法中选择,我们的示例选择set方法注入。
在List结构的集合数据注⼊时, array , list , set 这三个标签通⽤,另外注值的 value 标签内部可以直接写值,也可以使⽤ bean 标签配置⼀个对象,或者⽤ ref 标签引⽤⼀个已经配合的bean的唯⼀标识。
在Map结构的集合数据注⼊时,map 标签使⽤ entry ⼦标签实现数据注⼊,entry 标签可以使⽤key和value属性指定存⼊map中的数据。使⽤value-ref属性指定已经配置好的bean的引⽤。同时 entry 标签中也可以使⽤ ref 标签,但是不能使⽤ bean 标签。⽽ property 标签中不能使⽤ ref 或者 bean 标签引⽤对象。
- 依赖注入分类
1.3 xml与注解相结合模式
注意:
- 实际企业开发中,纯xml模式使⽤已经很少了
- 引⼊注解功能,不需要引⼊额外的jar
- xml+注解结合模式,xml⽂件依然存在,所以,spring IOC容器的启动仍然从加载xml开始
- 哪些bean的定义写在xml中,哪些bean的定义使⽤注解
第三⽅jar中的bean定义在xml,⽐如德鲁伊数据库连接池⾃⼰开发的bean定义使⽤注解
- xml中标签与注解的对应(IOC)
xml形式 | 对应的注解形式 |
---|---|
标签 | @Component("accountDao"), 注解加在类上,bean的id属性内容直接配置在注解后面,默认定义这个bean的id是类的类名首字母小写; 另外,针对分层代码开发提供了@Component的三种别名,@Controoler、@Service、@Repository分别控制层类、服务层类、dao层类的bean定义,这四个注解的用法完全一样,只是为了更清晰的区别 |
标签的scope属性 | @Scope("prototype"),默认单例,注解加在类上 |
标签的init-method属性 | @PostConstruct,注解加在方法上,该方法就是初始化后调用的方法 |
标签的destory-method属性 | @PreDestory,注解加在方法上,该方法就是销毁前调用的方法 |
- DI依赖注入的注解实现方式
- @Autowire(推荐使用)
@Autowired为Spring提供的注解,需要导⼊包org.springframework.beans.factory.annotation.Autowired。
@Autowire采用的策略为按照类型注入。
public class TransferServiceImpl {
@Autowired
private AccountDao accountDao;
}
如上代码所示,这样装配回去spring容器中找到类型为AccountDao的类,然后将其注⼊进来。这样会产⽣⼀个问题,当⼀个类型有多个bean值的时候,会造成⽆法选择具体注⼊哪⼀个的情况,
这个时候我们需要配合着@Qualifier使⽤。
@Qualifier告诉Spring具体去装配那个对象。
public class TransferServiceImpl {
@Autowired
@Qualifier(name="jdbcAccountDaoImpl")
private AccountDao accountDao;
}
这个时候我们就可以通过类型和名称定位到我们想注入的对象。
- @Resouce
@Resource 注解由 J2EE 提供,需要导⼊包 javax.annotation.Resource。
@Resource 默认按照 ByName ⾃动注⼊。
public class TransferService {
@Resource
private AccountDao accountDao;
@Resource(name="studentDao")
private StudentDao studentDao;
@Resource(type="TeacherDao")
private TeacherDao teacherDao;
@Resource(name="manDao",type="ManDao")
private ManDao manDao;
}
- 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配。
- 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛异常。
- 如果指定了type,则从上下文中查找类似匹配的唯一bean进行装配,找不到或找到多个则抛异常。
- 如果既没有指定name也没有指定type,则自动按照byName方式进行装配。
1.4 纯注解模式
改造xm+注解模式,将xml中遗留的内容全部以注解的形式迁移出去,最终删除xml,从Java配置类启动。
对应注解
@Configuration注解,表示当前类是一个配置类
@ComponentScan注解,代替context:componentr-scan
@PropertySource,引入其他配置类
@Import,引入其他配置类
@Value对变量赋值,可以直接赋值,也可以使用${}读取资源配置文件中的信息
@Bean将方法返回对象加入Spring IOC容器