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而言,这种表述更直接
  1. 配置形式:基于XML文件的方式
  2. Bean的配置方式:通过全类名(反射)、通过工厂方法(静态工厂方法&实例工厂方法)、FactoryBean
  3. IOC容器BeanFactory&ApplicationContext概述
  4. 依赖注入的方式:属性注入;构造器注入
  5. 注入属性值细节
  6. 自动装配
  7. bean之间的关系:继承、依赖
  8. bean的作用域:singleton;prototype'WEB环境作用域
  9. 使用外部属性文件
  10. spEL
  11. IOC容器中Bean的生命周期
  12. 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根目录的路径中完成初始化工作

四、依赖注入的方式

  1. 属性注入
    • 属性注入即通过setter方法注入Bean属性值或依赖的对象
    • 属性注入使用元素,使用name属性指定Bean的属性名称,value属性或子节点指定属性值
    • 属性注入是实际应用中最常用的注入方式
<bean >
    <property name="name" value="Spring"></property>
</bean>
  1. 构造器注入
    • 通过构造方法注入Bean的属性值或依赖的对象,它保证了Bean实例在实例化后就可以使用
    • 构造器注入在元素里声明属性没有name属性
    • 使用构造器注入属性值可以指定参数的位置index属性,也可以指定参数的类型type属性。以区分重载的构造器
  2. 工厂方法注入(很少使用,不推荐)

五、字面值

  • 字面值:可用字符串表示的值,可以通过元素标签或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之间的关系:继承、依赖

  1. 继承:使用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的生命周期
    1. 通过构造器或工厂方法创建Bean实例
    2. 为Bean的属性设置值和对其他Bean的引用
    3. 将Bena实例传递给Bean后置处理器的postProcessBeforeInitialization方法
    4. 调用Bean的初始化方法
    5. 将Bena实例传递给Bean后置处理器的postProcessAfterInitialization方法
    6. Bean可以使用了
    7. 当容器关闭时,调用Bean的销毁方法

十五、通过工厂方法配置Bean

  1. 静态工厂方法
<!--通过静态工厂方法配置bean-->
<!--    class:指向静态工厂方法的全类名
    factory-method:指向静态工厂方法的名字
    constructor-arg:如果工厂方法需要传入参数,则使用constructor-arg来配置参数
-->
    <bean >
        <constructor-arg value="Ford"></constructor-arg>
    </bean>
  1. 实例工厂方法
<!--    配置工厂的实例-->
    <bean ></bean>
<!--    通过实例工厂配置bean-->
<!--    factory-bean:指向实例工厂方法的bean
    factory-method:指向实例工厂方法名
    constructor-arg:如果工厂方法需要传入参数,则使用constructor-arg来配置参数
-->
    <bean >
        <constructor-arg value="Audi"></constructor-arg>
    </bean>
  1. 通过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中可以为子类注入子类对应的泛型类型成员变量的引用
  • 两个泛型类之间的依赖关系,泛型的实现类会继承依赖