[模块二]Spring IOC应用
Posted cn-zhou
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[模块二]Spring IOC应用相关的知识,希望对你有一定的参考价值。
【1】Spring IOC 基础
文件名 | 说明 |
---|---|
beans.xml | 定义需要实例化对象的类的全限定类名以及类之间依赖关系描述。 |
BeanFactory.java | 通过反射技术来实例化对象并维护对象之间的依赖关系。 |
Spring框架的IOC实现(3种):
-
纯xml(bean信息定义全部配置在xml中):
// JavaSE应用 // 方式一 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml"); // 方式二 new FileSystemXmlApplicationContext("c:/beans.xml"); // JavaWeb应用 ContextLoaderListener(监听器去加载xml)
-
xml+注解(部分bean使用xml定义,bean使用注解定义)
// JavaSE应用 // 方式一 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml"); // 方式二 new FileSystemXmlApplicationContext("c:/beans.xml"); // JavaWeb应用 ContextLoaderListener(监听器去加载xml)
-
纯注解(所有的bean都是用注解定义)
// JavaSE应用 ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class); // JavaWeb应用 ContextLoaderListener(监听器去加载注解配置类)
1.1 BeanFactory与ApplicationContext区别
名称 | 说明 |
---|---|
BeanFactory | Spring框架中IOC容器的顶层接口,只是用来定义一些基础功能和基础规范。 |
ApplicationContext | 是BeanFactory的一个子接口,具备BeanFactory提供的全部功能。 |
-
两个实现类基于xml配置:
- ClassPathXmlApplicationContext
- FileSystemXmlApplicationContext
-
基于注解配置的实现类:
- AnnotationConfigApplicationContext
-
启动IOC容器的方式
-
Java环境下启动IOC容器
- ClassPathXmlApplicationContext:从类的根路径下加载配置文件(推荐使用)
- FileSystemXmlApplicationContext:从磁盘路径上加载配置文件
- AnnotationConfigApplicationContext:纯注解模式下启动Spring容器
-
Web环境下启动IOC容器
-
从xml启动容器
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>Archetype Created Web Application</display-name> <!--配置Spring ioc容器的配置?件--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <!--使?监听器启动Spring的IOC容器--> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> </web-app>
-
从配置类启动容器
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>Archetype Created Web Application</display-name> <!--告诉ContextloaderListener知道我们使?注解的?式启动ioc容器--> <context-param> <param-name>contextClass</param-name> <param-value>org.springframework.web.context.support.AnnotationConfigWebAppli cationContext</param-value> </context-param> <!--配置启动类的全限定类名--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>com.lagou.edu.SpringConfig</param-value> </context-param> <!--使?监听器启动Spring的IOC容器--> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> </web-app>
-
-
1.2 纯XML模式
1.xml文件头
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
2.实例化Bean的三种方式
-
方式一:使用无参构造函数
在默认情况下,它会通过反射调??参构造函数来创建对象。如果类中没有?参构造函数,将创建失败。
<!--配置service对象--> <bean id="userService" class="com.lagou.service.impl.TransferServiceImpl"></bean>
-
方式二:使用静态方法创建
在实际开发中,我们使?的对象有些时候并不是直接通过构造函数就可以创建出来的,它可能在创建的过程 中会做很多额外的操作此时会提供?个创建对象的?法,恰好这个?法是static修饰的?法,即是此种情况。
<!--使?静态?法创建对象的配置?式--> <bean id="userService" class="com.lagou.factory.BeanFactory"factory-method="getTransferService"></bean>
-
方式三:使用实例化方法创建
此种?式和上?静态?法创建其实类似,区别是?于获取对象的?法不再是static修饰的了,?是类中的?个普通?法。此种?式?静态?法创建的使??率要??些。
<!--使?实例?法创建对象的配置?式--> <bean id="beanFactory" class="com.lagou.factory.instancemethod.BeanFactory"></bean> <bean id="transferService" factory-bean="beanFactory" factory-method="getTransferService"></bean>
3.Bean的X及生命周期
- 作用范围的改变
- 单例模式[singleton](默认):生命周期与容器相同。
- 多例模式[prototype]:spring框架只负责创建,不负责销毁。
4.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对象装配后调?。必须是?个?参?法。 |
destroy-method | ?于指定bean对象的销毁?法,此?法会在bean对象销毁前执?。它只能为scope是singleton时起作?。 |
5.DI依赖注入的xml配置
-
依赖注入分类
-
按照注入的方式分类
类别 说明 构造函数注入 顾名思义,就是利?带参构造函数实现对类成员的数据赋值。 set方法注入 它是通过类成员的set?法实现数据的注?。(使?最多的) -
按照注入的数据类型分类
类别 说明 基本类型和String 注?的数据类型是基本类型或者是字符串类型的数据。 其他Bean类型 注?的数据类型是对象类型,称为其他Bean的原因是,这个对象是要求出现在IoC容器中的。那么针对当前Bean来说,就是其他Bean了。 复杂类型(集合类型) 注?的数据类型是Aarry,List,Set,Map,Properties中的?种类型。
-
-
依赖注入的配置实现之构造函数注入
-
顾名思义,就是利?构造函数实现对类成员的赋值。它的使?要求是,类中提供的构造函数参数个数必须和配置的参数个数?致,且数据类型匹配。同时需要注意的是,当没有?参构造时,则必须提供构造函数参数的注?,否则Spring框架会报错。
-
在使用构造函数注入的时候,涉及的标签是constructor-arg,该标签有如下属性:
属性名称 说明 name ?于给构造函数中指定名称的参数赋值。 index ?于给构造函数中指定索引位置的参数赋值。 value ?于指定基本类型或者String类型的数据。 ref ?于指定其他Bean类型的数据。写的是其他bean的唯?标识。
-
-
依赖注入的配置实现之set方法注入
-
顾名思义,就是利?字段的set?法实现赋值的注??式。此种?式在实际开发中是使?最多的注??式。
-
在使用set方法注入时,需要使用property标签,该标签属性如下:
属性名称 说明 name 指定注?时调?的set?法名称。(注:不包含set这三个字?,druid连接池指定属性名称) value 指定注?的数据。它?持基本类型和String类型。 ref 指定注?的数据。它?持其他bean类型。写的是其他bean的唯?标识。复杂类型数据,它指的是集合类型数据。集合分为两类,?类是List结构(数组结构),?类是Map接?(键值对)。
-
1.3 XML与注解相结合模式
注意点:
- 实际企业开发中,纯XML模式使用很少了;
- 引入注解功能不需要引入额外的jar;
- xml+注解结合模式,xml文件依然存在,所以,spring IOC容器的启动仍然从加载xml开始;
- 第三方jar中的bean定义在xml中,比如德鲁伊数据库连接池;自己开发的bean的定义使用注解。
-
xml中标签和注解的对应(IOC)
xml形式 对应的注解形式 标签 @Component("accountDao"),注解加在类上。bean的id属性内容直接配置在注解后?如果不配置,默认定义个这个bean的id为类的类名?字??写;另外,针对分层代码开发提供了@Componenet的三种别名@Controller、@Service、@Repository分别?于控制层类、服务层类、dao层类的bean定义,这四个注解的?法完全?样,只是为了更清晰的区分?已。 标签的scope属性 @Scope("prototype"),默认单例,注解加在类上。 标签的init-method属性 @PostConstruct,注解加在?法上,该?法就是初始化后调?的?法。 标签的destroy-method属性 @PreDestory,注解加在?法上,该?法就是销毁前调?的?法。 -
DI依赖注入的注解实现方式
-
@Autowired(推荐使用)
- @Autowired为Spring提供的注解,需要导包;
- @Autowired采取的策略是按类型注入。当一个类型有多个bean值的时候,会造成无法选择具体注入哪一个的情况,这个时候就需要配合@Qualifier使用。@Qualifier告诉Spring具体装配哪个对象。这个时候我们就可以通过类型和名称定位到我们想注?的对象。
-
@Resource
@Resource在jdk11中已经移除,如果使用要单独导入jar包。
- @Resource注解由J2EE提供,需要导入包;
- @Resource默认按照ByName自动注入。
- 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到就抛出异常;
- 如果指定了name,则从上下文中找到名称匹配的bean进行装配,找不到则抛出异常;
- 如果指定了type,则从上下文找到类似匹配的唯一bean进行装配,找不到或是找到多个,都会抛出异常。
- 如果既没有指定name,又没有指定type,则自动按照ByName方式进行装配。
-
1.4 纯注解模式
注解名 | 说明 |
---|---|
@Confifiguration | 表名当前类是?个配置类 |
@ComponentScan | 替代 context:component-scan |
@PropertySource | 引?外部属性配置?件 |
@Import | 引?其他配置类 |
@Value | 对变量赋值,可以直接赋值,也可以使? ${} 读取资源配置?件中的信息 |
@Bean | 将?法返回对象加? SpringIOC 容器 |
【2】Spring IOC高级特性
2.1 lazy-Init延迟加载
应用场景
- 开启延迟加载一定程度提高容器启动和运转性能;
- 对于不常使用的Bean设置延迟加载,这样偶尔使用的时候再加载,不必要从一开始该Bean就占用资源。
Bean的延迟加载(延迟创建)
原因:ApplicationContext容器的默认行为是在启动服务器时将所有singleton bean提前实例化。默认lazy-init=“false”。
2.2 FactoryBean和BeanFactory
名称 | 说明 |
---|---|
FactoryBean | BeanFactory接?是容器的顶级接?,定义了容器的?些基础?为,负责?产和管理Bean的?个??,具体使?它下?的?接?类型,?如ApplicationContext。 |
BeanFactory | Spring中Bean有两种,?种是普通Bean,?种是??Bean(FactoryBean),FactoryBean可以?成某?个类型的Bean实例(返回给我们),也就是说我们可以借助于它?定义Bean的创建过程。 |
2.3 后置处理器
Spring提供了两种后处理bean的扩展接?,分别为 BeanPostProcessor 和BeanFactoryPostProcessor,两者在使?上是有所区别的。
接口名称 | 说明 |
---|---|
BeanPostProcessor | BeanPostProcessor是针对Bean级别的处理,可以针对某个具体的Bean.该接?提供了两个?法,分别在Bean的初始化?法前和初始化?法后执?,具体这个初始化?法指的是什么?法,类似我们在定义bean时,定义了init-method所指定的?法。定义?个类实现了BeanPostProcessor,默认是会对整个Spring容器中所有的bean进?处理。如果要对具体的某个bean处理,可以通过?法参数判断,两个类型参数分别为Object和String,第?个参数是每个bean的实例,第?个参数是每个bean的name或者id属性的值。所以我们可以通过第?个参数,来判断我们将要处理的具体的bean。注意:处理是发?在Spring容器的实例化和依赖注?之后。 |
BeanFactoryPostProcessor | BeanFactory级别的处理,是针对整个Bean的??进?处理,典型应?:PropertyPlaceholderConfifigurer,此接?只提供了?个?法,?法参数为ConfifigurableListableBeanFactory,该参数类型定义了?些?法。其中有个?法名为getBeanDefifinition的?法,我们可以根据此?法,找到我们定义bean的BeanDefifinition对象。然后我们可以对定义的属性进?修改,?法名字类似我们bean标签的属性,setBeanClassName对应bean标签中的class属性,所以当我们拿到BeanDefifinition对象时,我们可以?动修改bean标签中所定义的属性值。BeanDefifinition对象:我们在 XML 中定义的 bean标签,Spring 解析 bean 标签成为?个 JavaBean,这个JavaBean 就是 BeanDefifinition。注意:调? BeanFactoryPostProcessor ?法时,这时候bean还没有实例化,此时 bean 刚被解析成BeanDefifinition对象。 |
以上是关于[模块二]Spring IOC应用的主要内容,如果未能解决你的问题,请参考以下文章