spring配置bean 一、配置Bean 二、Spring容器 三、ApplicationContext 四、依赖注入的方式 五、字面值 六、引用其它Bean 七、注入参数详解:null值和级联属性 八、配置集合属性 十、Bean之间的关系:继承、依赖 十一、Bean的作用域使用bean的scope属性来配置bean的作用域 十二、使用外部属性文件 十三、Spring表达式语言:SpEL(与EL用法相似) 十四、IOC容器中bean的生命周期方法 十五、通过工厂方法配置Bean 十六、通过注解配置bean 十七、泛型依赖注入
spring的核心思想
- IOC(Inversion of Control):其思想是反转资源获取的方向,传统的资源查找方式要求组件向容器发起请求查找资源。作为回应,容器适时的返回资源。而应用了IOC之后,则是容器主动的将资源推送给它所管理的组件,组件所要做的仅是选择一种合适的方法来接收资源。这种行为也被称为查找的被动形式。
- DI(Dependency Injection)-IOC的另一种表述方式:即组件以一些预先定义好的方式(例如:setter方法)接收来自如容器的资源注入。相对于IOC而言,这种表述更直接
- 配置形式:基于XML文件的方式
- Bean的配置方式:通过全类名(反射)、通过工厂方法(静态工厂方法&实例工厂方法)、FactoryBean
- IOC容器BeanFactory&ApplicationContext概述
- 依赖注入的方式:属性注入;构造器注入
- 注入属性值细节
- 自动装配
- bean之间的关系:继承、依赖
- bean的作用域:singleton;prototype'WEB环境作用域
- 使用外部属性文件
- spEL
- IOC容器中Bean的生命周期
- Spring4.x新特性:泛型依赖注入
<!-- 配置beanclass:bean 的全类名,通过反射的方式在IOC容器中创建bean,所以要求Bean中必须有无参构造器id:标识容器bean,id唯一-->
<bean >
<property name="Name" value="Spring"></property>
</bean>
二、Spring容器
- 在SpringIOC容器读取Bean配置创建Bean实例之前,必须对它进行实例化。只有在容器实例化后,才可以从IOC容器里获取Bean实例并使用
- Spring提供了两种类型的IOC容器实现
- BeanFactory:IOC容器的基本实现
- ApplicationContext:提供了更多的高级特性,是BeanFactory的子接口
- BeanFactory是Spring框架的基础设施,面向Spring本身;ApplicationContext面向Spring框架的开发者,几乎所有的应用场合都直接使用ApplicationContext而非底层的BeanFactory。
- 无论使用何种方式,配置文件是相同的
三、ApplicationContext
- ApplicationContext的主要实现类
- ClassPathXmlApplicationContext:从类路径下加载配置文件
- FileSystemXmlApplicationContext:从文件系统中加载配置文件
- ConfigurableApplicationContext扩展于ApplicationContext,新增加两个主要方法:refresh()和close(),让ApplicationContext具有启动、刷新、关闭上下文的功能
- ApplicationContext在初始化上下文时就实例化所有的单例Bean
- WebApplicationContext是专门为WEB应用而准备的,它允许从相对于WEB根目录的路径中完成初始化工作
四、依赖注入的方式
- 属性注入
- 属性注入即通过setter方法注入Bean属性值或依赖的对象
- 属性注入使用
元素,使用name属性指定Bean的属性名称,value属性或 子节点指定属性值 - 属性注入是实际应用中最常用的注入方式
<bean >
<property name="name" value="Spring"></property>
</bean>
- 构造器注入
- 通过构造方法注入Bean的属性值或依赖的对象,它保证了Bean实例在实例化后就可以使用
- 构造器注入在
元素里声明属性 没有name属性 - 使用构造器注入属性值可以指定参数的位置index属性,也可以指定参数的类型type属性。以区分重载的构造器
- 工厂方法注入(很少使用,不推荐)
五、字面值
- 字面值:可用字符串表示的值,可以通过
元素标签或value属性进行注入。 - 基本数据类型及其封装类、String等类型都可以采取字面值注入的方式
- 若字面值中包含特殊字符,可以使用把字面值包裹起来。
六、引用其它Bean
- 组成应用程序的Bean经常需要相互协作以完成应用程序的功能。要使Bean能够相互访问,就必须在Bean配置文件中指定对Bean的引用
- 在Bean的配置文件中,可以通过元素或ref属性为Bean的属性或构造器参数指定对Bean的引用
<bean >
<property name="name" value="张三"></property>
<property name="age" value="24"></property>
<property name="car" ref="car2"></property>
</bean>
- 也可以在属性或构造器里包含Bean的声明,这样的bean称为内部bean。内部bean不能被外部使用
<property name="car">
<bean class="com.atguigu.spring.beans.Car">
<constructor-arg value="Ford"></constructor-arg>
<constructor-arg value="Changan"></constructor-arg>
<constructor-arg value="2000000" type="double"></constructor-arg>
</bean>
</property>
七、注入参数详解:null值和级联属性
- 可以使用专用的
元素标签为Bean的字符串或其他对象类型的属性注入null值 - 和Struts、Hiberante等框架一样,Spring支持级联属性的配置。属性要先初始化后才能赋值,否则会异常。
<bean >
<constructor-arg name="name" value="李四"></constructor-arg>
<constructor-arg name="age" value="30"></constructor-arg>
<constructor-arg name="car" ref="car"></constructor-arg>
<property name="car.maxSpeed" value="11111"></property>
</bean>
八、配置集合属性
- 在Spring中可以通过内置的xml标签(例如
- 、
、 - 配置java.util.List类型的属性,需要指定
- 标签,在标签里包含一些元素。这些标签可以通过
指定简单的常量值,通过指定对其他Bean的引用。通过 指定内置Bean定义。通过 指定空元素。甚至可以内嵌其他集合 - 数组的定义和List一样,都使用
- 配置java.util.Set需要使用
标签,定义元素的方法与list一样
<bean >
<property name="name" value="王五"></property>
<property name="age" value="40"></property>
<property name="cars">
<list>
<ref bean="car"></ref>
<ref bean="car2"></ref>
</list>
</property>
</bean>
- 配置Map类型的值
<bean >
<property name="name" value="Rose"></property>
<property name="age" value="36"></property>
<property name="cars">
<map>
<entry key="AA" value-ref="car"></entry>
<entry key="BB" value-ref="car2"></entry>
</map>
</property>
</bean>
- 配置Properties属性值
<bean >
<property name="properties" >
<props>
<prop key="user">root</prop>
<prop key="password">123456</prop>
<prop key="jdbcUtil">jdbc:mysql//localhost:3306?test</prop>
<prop key="driverClass">com.mysql.cj.jdbc.Driver</prop>
</props>
</property>
</bean>
- 配置独立的集合bean,以供多个bean进行引用
<util:list >
<ref bean="car"></ref>
<ref bean="car2"></ref>
</util:list>
<bean >
<property name="name" value="Jack"></property>
<property name="age" value="42"></property>
<property name="cars" ref="cars"></property>
</bean>
- 通过p命名空间为属性赋值
<bean ></bean>
``
# 九、自动装配
- Spring IOC容器扩自动装配Bean,需要做的仅仅是在<bean>的autowire属性里指定自动装配的模式
- byType(根据类型自动装配):若IOC容器中有多个与目标Bean类型一致的Bean。在这种情况下,Spring将无法判定哪个Bean最合适该属性,所以不能执行自动装配,抛出异常。
- byName(根据名称自动装配):必须将目标Bean的名称和属性名设置的完全相同。
```xml
<bean ></bean>
<bean ></bean>
<bean ></bean>
- constructor(通过构造器自动装配):当Bean中存在多个构造器时,此种自动装配方式将会很复杂。不推荐使用
XML配置里的Bean自动装配的缺点
- 在Bean配置文件里设置autowire属性进行自动装配将会装配Bean的所有属性。然而,若只希望装配个别属性时,autowire属性就不够灵活了
- autowire属性要么根据类型自动装配,要么根据名称自动装配,不能两者兼而有之
- 一般情况下,在实际的项目中很少使用自动装配功能,明确清晰的配置文档更有说服力一些
十、Bean之间的关系:继承、依赖
- 继承:使用parent属性
- Spring允许继承bean的配置,被继承的bean称为父bean。继承这个父bean的bean称为子Bean
- 子bean从父bean中继承配置,包括bean的属性配置
- 子bean也可以覆盖从父bean继承过来的配置
- 父bean可以作为配置模板,也可以作为bean实例。若只想把父bean作为模板,可以设置
的abstract属性为true,这样Spring将不会实例化这个bean - 并不是
元素里的所有属性都会被继承。比如:autowire,abstract等 - 也可以忽略父bean的class属性,让子bean指定自己的类,而共享相同的属性配置,但此时abstract必须设为true
<bean ></bean>
<bean ></bean>
2.依赖depends-on
配置bean时必须关联指定的bean,换句话说,就是一个bean需要依赖另一个bean
- Spring允许用户通过depends-on属性设定Bean前置依赖的Bean,前置依赖的Bean会在本Bean实例化之前创建好
- 如果前置依赖于多个Bean,则可以通过逗号,空格或的方式配置Bean的名称
十一、Bean的作用域使用bean的scope属性来配置bean的作用域
- singleton:默认值,单例。容器初始化时创建bean实例,在整个生命周期内只创建这一个bean。
- prototype:原型的。容器初始化时不创建bean的实例。而在每次请求时都创建一个新的bean的实例,并返回
十二、使用外部属性文件
- 在配置文件里配置bean时,有时需要在bean的配置里混入系统部署的细节信息(例如:文件路径,数据源配置信息等)。而这些部署细节实际上需要和bean配置相分离
- Spring提供了一个PropertyPlaceholderConfigurer的BeanFacotry后置处理器,这个处理器允许用户将Bean配置的部分内容外移到属性文件中。可以在Bean配置文件里使用形式为${var}的变量,PropertyPlaceholderConfigurer从属性文件里加载属性,并使用这些属性来替换变量。
- Spring还允许在属性文件中使用${proName},以实现属性之间的相互引用。
在db.properties文件中有以下内容
url=jdbc:mysql://localhost:3306/test?serverTimezone=UTC
user=root
password=123456
driverClassName=com.mysql.cj.jdbc.Driver
使用此属性文件配置
<!--导入属性文件-->
<content:property-placeholder location="classpath:db.properties"/>
<bean >
<property name="url" value="${url}"></property>
<property name="username" value="${user}"></property>
<property name="password" value="${password}"></property>
<property name="driverClassName" value="${driverClassName}"></property>
</bean>
注:由于JVM中也存在属性username,并且可以使用${username}获取,故db.properties中用户名不要使用username。
十三、Spring表达式语言:SpEL(与EL用法相似)
- Spring表达式语言(简称SpEL):是一个支持运行时查询和操作对象图的强大的表达式语言
- 语法类似于EL:SpEL使用#{}作为定界符,所有在大括号中的字符都将被认为是SpEL
- SpEL为bean的属性进行动态赋值提供了便利
- 通过SpEL可以实现:
- 通过bean的id对bean进行引用
- 调用方法以及引用对象中的属性
- 计算表达式的值
- 正则表达式的匹配
<bean >
<property name="name" value="张三"></property>
<!--使用spel引用其它类-->
<property name="car" value="#{car}"></property>
<!--使用spel使用其它bean的属性 -->
<property name="city" value="#{address.city}"></property>
<property name="info" value="#{car.price>3000000?'这是一辆好车':'这是一辆普通的车'}"></property>
</bean>
十四、IOC容器中bean的生命周期方法
-
SpringIOC容器可以管理Bean的生命周期,Spring允许在Bean生命周期的特定点执行定制的任务。
-
SpringIOC容器对Bean的生命周期进行管理的过程:
- 通过构造器或工厂方法创建Bean实例
- 为Bean的属性设置值和对其他Bean的引用
- 调用Bean的初始化方法
- Bean可以使用了
- 当容器关闭时,调用Bean的销毁方法
-
在Bean的声明里设置init-method和destroy-method属性,为Bean指定初始化和销毁方法
-
创建Bean后置处理器
- Bean后置处理器允许在调用初始化方法前后对Bean进行额外的处理
- Bean后置处理器对IOC容器里的所有Bean实例逐一处理,而非单一实例。其典型应用是:检查Bean属性的正确性或根据特定的标准更改Bean的属性
- 对Bean后置处理器而言,需要实现Interface BeanPostProcessor接口。在初始化方法被调用前后,Spring将把每个Bean实例分别传递给上述接口的以下两个方法
<!--配置bean的后置处理器 不需要配置id IOC自动识别是一个BeanPostProcessor-->
<!--实现BeanPostProcessor接口,并具体实现
public Object postProcessBeforeInitialization(Object bean, String beanName) 在init-method之前调用
public Object postProcessAfterInitialization(Object bean, String beanName) 在init-method之后调用
两个方法
bean 实例本身
beanName:IOC容器配置的bean的名字
返回值:返回给用户的bean,可修改
-->
<bean ></bean>
- 添加Bean后置处理器后Bean的生命周期
- 通过构造器或工厂方法创建Bean实例
- 为Bean的属性设置值和对其他Bean的引用
- 将Bena实例传递给Bean后置处理器的postProcessBeforeInitialization方法
- 调用Bean的初始化方法
- 将Bena实例传递给Bean后置处理器的postProcessAfterInitialization方法
- Bean可以使用了
- 当容器关闭时,调用Bean的销毁方法
十五、通过工厂方法配置Bean
- 静态工厂方法
<!--通过静态工厂方法配置bean-->
<!-- class:指向静态工厂方法的全类名
factory-method:指向静态工厂方法的名字
constructor-arg:如果工厂方法需要传入参数,则使用constructor-arg来配置参数
-->
<bean >
<constructor-arg value="Ford"></constructor-arg>
</bean>
- 实例工厂方法
<!-- 配置工厂的实例-->
<bean ></bean>
<!-- 通过实例工厂配置bean-->
<!-- factory-bean:指向实例工厂方法的bean
factory-method:指向实例工厂方法名
constructor-arg:如果工厂方法需要传入参数,则使用constructor-arg来配置参数
-->
<bean >
<constructor-arg value="Audi"></constructor-arg>
</bean>
- 通过FactoryBean配置Bean
- 创建一个实现FactoryBean接口的类
- 通过FactoryBean来配置Bean的实例
<!-- 通过FactoryBean来配置Bean的实例
class:指向FactoryBean的全类名
property::配置FactoryBean的属性
但实际返回的是FactoryBean的getObject()方法返回的实例
-->
<bean >
<property name="brand" value="BWM"></property>
</bean>
十六、通过注解配置bean
-
组件扫描(component scanning):Spring能够从classpath下自动扫描,侦测和实例化具有特定注解的组件
-
特定组件包括
- @Component:基本注解,标识了一个受Spring管理的组件
- @Respository:标识持久层组件
- @Service:标识服务层(业务层)组件
- @Controller:标识表现层组件
-
对于扫描到的组件,Spring有默认的命名策略:使用非限定类名,第一个字母小写。也可以在注解中通过value属性值标识组件的名称。
-
当在组件类上使用了特定的注解之后,还需要在Spring的配置文件中声明context:component-scan:
- basse-package属性指定一个需要扫描的基类包,Spring容器将会扫描这个基类包里及其子包中的所有类。
- 当需要扫描多个包时,可以使用逗号分隔
- 如果仅希望扫描特定的类而非基包下的所有类,可使用resource-pattern属性过滤特定的类,示例:<context:component-scan base-package="com.atguigu.spring.beans" resource-pattern="autowire/*.class">
- <context:include-filter>子节点表示要包括的目标类。要在<context:component-scan>中设置属性use-default-filters="false"
- <context:exclude-filter>子节点表示要排除在外的目标类
- <context:component-scan>下可以拥有若干个<context:include-filter>和<context:exclude-filter>子节点。使用type可以设置包含或排除类型。type="annotation | assignable"。注释或接口.
-
组件装配
- <context:component-scan>元素会自动注册AutowiredAnnotationBeanPostProcessor实例,该实例可以自动装配具有@Autowired和@Resource、@Inject注解的属性
-
使用@Autowired自动装配Bean
- 构造器,普通字段(即使是非public),一切具有参数的方法都可以应用@Autowired注解
- 默认情况下,所有使用@Autowired注解的属性都需要被设置,当Spring找不到匹配的Bean装配属性时,会抛出异常,若某一属性允许不被设置,可以设置@Autowired注解的required属性为false
- 默认情况下,当IOC容器里存在多个类型兼容的Beab时,通过类型的自动装配将无法工作。此时可以在@Qualifier注解里提供Bean的名称。Spring允许对方法的入参标注@Qualifier指定注入Bean的名称。
- @Autowired注解也可以应用在数组类型的属性上,此时Spring将会把所有匹配的Bean进行自动装配
- @Autowired注解也可以应用在集合属性上,此时Spring读取该集合的类型信息,然后自动装配所有与之兼容的Bean
- @Autowired注解用在java.util.Map上,若该Map的键值为String,那么Spring将自动装配与之Map值类型兼容的Bean,此时Bean的名称作为键值。
-
使用@Resource或@Inject自动装配Bean
- Spring还支持@Resource和@Inject注解,这两个注解和@Autowired注解的功能相似
- @Resource注解要求提供一个Bean名称的属性,若该属性为空,则自动采用标注处的变量或方法名作为Bean的名称
- @Inject和@Autowired注解一样也是按类型匹配注入的Bean,但没有required属性
- 建议使用@Autowired注解
十七、泛型依赖注入
- Spring4.x中可以为子类注入子类对应的泛型类型成员变量的引用
- 两个泛型类之间的依赖关系,泛型的实现类会继承依赖