Spring学习之IOC

 

配置 bean

配置形式:基于 XML 文件的方式;基于注解的方式

Bean 的配置方式:通过全类名(反射)、通过工厂方法(静态工厂方法 & 实例工厂方法)、FactoryBean

IOC 容器 BeanFactory & ApplicationContext概述

依赖注入的方式:属性注入;构造器注入

自动转配 :    auto属性,会自动给剩下的所有属性赋值

bean 之间的关系:parent和depends-on

bean 的作用域:singleton;prototype;WEB 环境作用域

使用外部属性文件

spEL

IOC 容器中 Bean 的生命周期

Spring 4.x 新特性:泛型依赖注入

 

 

IOC(Inversion of Control):其思想是反转资源获取的方向. 传统的资源查找方式要求组件向容器发起请求查找资源. 作为回应, 容器适时的返回资源. 而应用了IOC 之后, 则是容器主动地将资源推送给它所管理的组件, 组件所要做的仅是选择一种合适的方式来接受资源. 这种行为也被称为查找的被动形式

 

 <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:util="http://www.springframework.org/schema/util"
 xmlns:p="http://www.springframework.org/schema/p"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
 
 <!-- 配置一个 bean 一个bean标签代表给容器添加了一个对象.class用全类名表示通过反射方式实例化对象,所以类中需要一个无参的构造函数,-->
 <bean id="helloWorld" class="com.atguigu.spring.helloworld.HelloWorld">
  <!-- 为属性赋值 -->
  <property name="user" value="Jerry"></property>
 </bean>
 
 <!-- 配置一个 bean -->
 <bean id="helloWorld2" class="com.atguigu.spring.helloworld.HelloWorld">
  <!-- 为属性赋值 -->
  <!-- 通过属性注入: 通过 setter 方法注入属性值 -->
  <property name="user" value="Tom"></property>
 </bean>
 
 <!-- 通过构造器注入属性值 -->
 <bean id="helloWorld3" class="com.atguigu.spring.helloworld.HelloWorld">
  <!-- 要求: 在 Bean 中必须有对应的构造器.  -->
  <constructor-arg value="Mike"></constructor-arg>
 </bean>
 
 <!-- 若一个 bean 有多个构造器, 如何通过构造器来为 bean 的属性赋值 -->
 <!-- 可以根据 index 和 value 进行更加精确的定位. (了解) -->
 <bean id="car" class="com.atguigu.spring.helloworld.Car">
  <constructor-arg value="KUGA" index="1"></constructor-arg>
  <constructor-arg value="ChangAnFord" index="0"></constructor-arg>
  <constructor-arg value="250000" type="float"></constructor-arg>
 </bean>
 
 <bean id="car2" class="com.atguigu.spring.helloworld.Car">
  <constructor-arg value="ChangAnMazda"></constructor-arg>
  <!-- 若字面值中包含特殊字符, 则可以使用 CDATA 来进行赋值. (了解) -->
  <constructor-arg>
   <value><![CDATA[<ATARZA>]]></value>
  </constructor-arg>
  <constructor-arg value="180" type="int"></constructor-arg>
 </bean>
 
 <!-- 配置 bean -->
 <bean id="dao5" class="com.atguigu.spring.ref.Dao"></bean>
 <bean id="service" class="com.atguigu.spring.ref.Service">
  <!-- 引用类型用ref -->
  <property name="dao" ref="dao5"></property>
 </bean>
 
 <!-- 用bean标签来配置内部bean -->
 <bean id="service2" class="com.atguigu.spring.ref.Service">
  <property name="dao">
   <!-- 内部 bean, 类似于匿名内部类对象. 不能被外部的 bean 来引用, 也没有必要设置 id 属性 -->
   <bean class="com.atguigu.spring.ref.Dao">
    <property name="dataSource" value="c3p0"></property>
   </bean>
  </property>
 </bean>
 
 <bean id="action" class="com.atguigu.spring.ref.Action">
  <property name="service" ref="service2"></property>
  <!-- 设置级联属性(了解) -->
  <property name="service.dao.dataSource" value="DBCP2"></property>
 </bean>
 
 <bean id="dao2" class="com.atguigu.spring.ref.Dao">
  <!-- 为 Dao 的 dataSource 属性赋值为 null, 若某一个 bean 的属性值不是 null, 使用时需要为其设置为 null(了解) -->
  <property name="dataSource"><null/></property>
 </bean>
 
 <!-- 装配集合属性 -->
 <bean id="user" class="com.atguigu.spring.helloworld.User">
  <property name="userName" value="Jack"></property>
  <property name="cars">
   <!-- 集合属性就用个list标签 -->
   <list>
    <ref bean="car"/>
    <ref bean="car2"/>
   </list>
  </property>
 </bean>
 
 <!-- 用util命名空间将一个集合作为一个工具,其他类可以指向它 -->
 <util:list id="cars">
  <ref bean="car"/>
  <ref bean="car2"/>
 </util:list>
 
 <bean id="user2" class="com.atguigu.spring.helloworld.User">
  <property name="userName" value="Rose"></property>
  <!-- 引用外部声明的 list -->
  <property name="cars" ref="cars"></property>
 </bean>
 <!--使用p命名空间,能简化书写-->
 <bean id="user3" class="com.atguigu.spring.helloworld.User"
  p:cars-ref="cars" p:userName="Titannic"></bean>
  
 <!-- 用parent可以在配置文件中继承配置 --> 
 <bean id="user4" parent="user" p:userName="Bob"></bean>
 
 <bean id="user6" parent="user" p:userName="维多利亚"></bean>
 
 <!--depends-on,那么创建这个对象之前必须先创建好depengs-on的对象 --> 
 <bean id="user5" parent="user" p:userName="Backham" depends-on="user6"></bean>
 
</beans>

 <!-- 自动装配: 只声明 bean, 而把 bean 之间的关系交给 IOC 容器来完成 -->
 <!--  
  byType: 根据类型进行自动装配. 但要求 IOC 容器中只有一个类型对应的 bean, 若有多个则无法完成自动装配.
  byName: 若属性名和某一个 bean 的 id 名一致, 即可完成自动装配. 若没有 id 一致的, 则无法完成自动装配
 -->
 <!-- 在使用 XML 配置时, 自动转配用的不多. 但在基于 注解 的配置时, 自动装配使用的较多.  -->
 <bean id="dao" class="com.atguigu.spring.ref.Dao">
  <property name="dataSource" value="C3P0"></property>    
 </bean>
 
 <!-- 默认情况下 bean 是单例的! -->
 <!-- 但有的时候, bean 就不能使单例的. 例如: Struts2 的 Action 就不是单例的! 可以通过 scope 属性来指定 bean 的作用域 -->
 <!--  
  prototype: 原型的. 每次调用 getBean 方法都会返回一个新的 bean. 且在第一次调用 getBean 方法时才创建实例
  singleton: 单例的. 每次调用 getBean 方法都会返回同一个 bean. 且在 IOC 容器初始化时即创建 bean 的实例. 默认值 
 -->
 <bean id="dao2" class="com.atguigu.spring.ref.Dao" scope="prototype"></bean>
 
 <bean id="service" class="com.atguigu.spring.ref.Service" autowire="byName"></bean>
 
 <bean id="action" class="com.atguigu.spring.ref.Action" autowire="byType"></bean>
 
 <!-- 因为有些对象的属性是需要改变的,为了维护的方便,将配置信息写在外部的资源文件当中
      导入classpath下名字叫db.properties的资源文件 -->
 <context:property-placeholder location="classpath:db.properties"/>
 
 <!-- 配置数据源 用${配置文件中的属性名}引入-->
 <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
  <property name="user" value="${jdbc.user}"></property>
  <property name="password" value="${jdbc.password}"></property>
  <property name="driverClass" value="${jdbc.driverClass}"></property>
  <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
  
  <property name="initialPoolSize" value="${jdbc.initPoolSize}"></property>
  <property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>
 </bean>
 
 <!--spring表达式语言SpEL:使用 #{…} 作为定界符,所有在大框号中的字符都将被认为是 SpEL
 可以为属性进行动态的赋值,
 调用静态方法或静态属性:通过 T() 调用一个类的静态方法,它将返回一个 Class Object,
 然后 再调用相应的方法或属性
 支持运算符
 引用bean,和bean的属性和方法 -->
 <bean id="girl" class="com.atguigu.spring.helloworld.User">
  <property name="userName" value="周迅"></property>
 </bean>
 
 <bean id="boy" class="com.atguigu.spring.helloworld.User" init-method="init" destroy-method="destroy">
  <property name="userName" value="#{T(java.lang.MATH).PI*20}"></property>
  <property name="userName" value="高胜远"></property>
  <property name="wifeName" value="#{girl.userName}"></property>
 </bean>
 
 <!-- 配置 bean 后置处理器: 不需要配置 id 属性, IOC 容器会识别到他是一个 bean 后置处理器, 并调用其方法 -->
 <bean class="com.atguigu.spring.ref.MyBeanPostProcessor"></bean>

IOC容器管理bean的生命周期

 Spring IOC 容器可以管理 Bean 的生命周期, Spring 允许在 Bean 生命周期的特定点执行定制的任务.

在 Bean 的声明里设置 init-method 和 destroy-method 属性, 为 Bean 指定初始化和销毁方法.  

Spring IOC 容器对 Bean 的生命周期进行管理的过程:

     –通过构造器或工厂方法创建 Bean 实例

     –为 Bean 的属性设置值和对其他 Bean 的引用

     –调用 Bean 的初始化方法

     –Bean 可以使用了

     –当容器关闭时, 调用 Bean 的销毁方法

<!--init()和destory()方法都是类中声明的-->
<bean id="person" class="com.neusoft.person" p:name="zhangsan" init-method="init"
    destory-method="destory">
</bean>

 

Bean 后置处理器允许在调用初始化方法前后对 Bean 进行额外的处理.

Bean 后置处理器对 IOC 容器里的所有 Bean 实例逐一处理, 而非单一实例. 其典型应用是: 检查 Bean 属性的正确性或根据特定的标准更改 Bean 的属性.

对Bean 后置处理器而言, 需要实现接口BeanPostProcessor. 在初始化方法被调用前后, Spring 将把每个 Bean 实例分别传递给上述接口的以下两个方法:

postProcessBeforeInitialization()方法和 postProcessAfterInitialization()方法

 

通过调用静态工厂方法和实例工厂方法创建 Bean

 

wKioL1ZWeY_B05HIAALwMqIltxE251.png

wKiom1ZWeUKydlK0AAM3e2EA0Gw489.png

wKioL1ZWebGj25gLAAb2EecCCRQ514.png

 

factorybean的方式配置bean

        有些对象是通过系统给定的factorybean来配置得到的

        继承factorybean的类通过getobject方法返回一个对象,给放到容器中.

wKiom1ZWaF7BswpCAAN8lhTdGnI138.png

配置文件只需要知道factorybean的类和给类的属性赋值,然后就会给容器中添加factorybean的getObject()方法返回的对象

wKiom1ZWaGGhD_jAAATNj7k4N44933.png

 

通过注解配置bean

组件扫描(component scanning):  Spring 能够从 classpath下自动扫描, 侦测和实例化具有特定注解的组件

  

特定组件包括:

–@Component: 基本注解, 标识了一个受 Spring 管理的组件

–@Respository: 标识持久层组件

–@Service: 标识服务层(业务层)组件

–@Controller: 标识表现层组件

对于扫描到的组件, Spring 有默认的命名策略: 使用非限定类名, 第一个字母小写. 也可以在注解中通过 value 属性值标识组件的名称

 <!-- base-package 属性 Spring 容器将会扫描这个基类包里及其子包中的所有类. 当需要扫描多个包时, 可以使用逗号分隔 ,resource-pattern 属性过滤特定的类-->
<context:component-scan base-package="com.test.beans" 
            resourse-pattern="auto/*.class"/>
<!-- [!CDATA[<context:include-filter> 子节点表示要包含的目标类
     <context:exclude-filter> 子节点表示要排除在外的目标类
     <context:component-scan> 下可以拥有若干个 <context:include-filter> 和             <context:exclude-filter> 子节点]]-->

 

使用 @Autowired给属性注解

通过给属性加这个注解,spring就会自动给这个属性赋值. 

–构造器, 普通字段(即使是非 public), 一切具有参数的方法都可以应用@Authwired注解

–默认情况下, 所有使用 @Authwired注解的属性都需要被设置. 当 Spring 找不到匹配的 Bean 装配属性时, 会抛出异常, 若某一属性允许不被设置, 可以设置 @Authwired注解的 required 属性为 false

–默认情况下, 当 IOC 容器里存在多个类型兼容的 Bean 时, 通过类型的自动装配将无法工作. 此时可以在 @Qualifier 注解里提供 Bean 的名称. Spring 允许对方法的入参标注 @Qualifiter已指定注入 Bean 的名称

–@Authwired注解也可以应用在数组类型的属性上, 此时 Spring 将会把所有匹配的 Bean 进行自动装配.

–@Authwired注解也可以应用在集合属性上, 此时 Spring 读取该集合的类型信息, 然后自动装配所有与之兼容的 Bean.

@Authwired注解用在 java.util.Map上时, 若该 Map 的键值为 String, 那么 Spring 将自动装配与之 Map 值类型兼容的 Bean, 此时 Bean 的名称作为键值

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章