Spring学习记录(01)——装配Spring Bean

###0.前言
《Java EE互联网轻量级框架整合开发——SSM框架(Spring MVC+Spring+MyBatis)和Redis实现》

本文主要记录装配Spring Bean的学习笔记。

###1.Spring

  • Spring框架的核心理念是IoC(控制反转)和AOP(面向切面编程)。
  • Spring会认为一切java类都是资源,而资源都是Bean,容纳这些Bean的就是Spring所提供的IoC容器。(基于Bean的编程)
  • Spring中的IoC容器的实现方法是依赖注入(DI)(通常有两种方法:依赖查找和依赖注入)

IoC(控制反转):由容器帮助对象查找和注入资源属性,而非通过对象主动请求获取资源属性。

AOP(面向切面编程):将程序中的横切关注点模块化形成切面,通过切点匹配程序中的连接点,将切面织入到目标对象,即创建目标对象的代理对象。

IoC的两种实现方式:

  • 依赖查找:容器提供回调接口和上下文条件给组件。组件必须使用容器提供的API来查找资源和协作对象,仅有的控制反转只体现在那些回调方法上。容器将调用这些回调方法,从而让应用代码获得相关资源。

  • 依赖注入(DI):组件不做定位查询,只提供普通的Java方法让容器去决定依赖关系。容器全权负责的组件的装配,它会把符合依赖关系的对象通过JavaBean属性或者构造函数传递给需要的对象。

Spring的IoC容器是为了容纳开发中的各种Bean,并让开发者通过描述获取到Bean。(Bean可以是资源、java类等)

依赖注入的3种方式:

  1. 构造器注入:Spring采用反射的方式,通过使用构造方法来完成注入。
  2. 设值注入:Spring采用反射的方式,通过获取Java Bean规范的setter方法完成注入。(较为灵活和可读性高)
  3. 接口注入:从外部注入。(例如Tomcat配置数据库连接资源,通过JNDI的形式获取,生成连接实例)

构造器注入:

<bean id="role_1" class="com.ssm.chapter9.pojo.Role"> <!--对应Role(String,String)-->
    <constructor-arg index="0" value="高级工程师" /> <!--构造器第一个参数-->
    <constructor-arg index="1" value="重要人员" />   <!--构造器第二个参数-->
</bean>

setter注入:

<bean id="role_1" class="com.ssm.chapter9.pojo.Role">
    <property name="roleName" value="高级工程师" />  <!--对应setRoleName(String)-->
    <property name="note" value="重要人员" />        <!--对应setNote(String)-->
</bean>

接口注入:(配置Tomcat数据源)

//Tomcat的context.xml,Tomcat的lib目录下需要mysql的驱动包
<?xml version='1.0' encoding='UTF-8' ?>
<Context>
<Resource name="jdbc/ssm"  <!--JNDI名称-->
auth="Container"
type="javax.sql.DataSource"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/ssm?zeroDataTimeBehavior=convertToNull" <!--数据库的JDBC连接-->
userName="root"
password="root"
/>
</Context>

//spring配置
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName"> 
        <value>java:comp/env/jdbc/ssm</value>
    </property>
</bean>

###2.Spring Bean的装配
Spring Bean的装配有3种方式:

  1. xml配置
  2. java的接口和类中实现配置(注解配置)
  3. 隐式bean的发现机制(组件扫描等)和自动装配原则

配置的使用优先级遵循:基于约定优于配置原则。(即 使用优先级: 3 > 2 > 1)

普遍推荐的做法:

  • 第三方库的配置放入xml中,便于维护和理解
  • 自身开发的使用注解进行配置。

###2.1 XML的配置
在使用xml配置bean的时候,需要注意xml模板文件的导入。

xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd

简易的装配示例:

<bean id="permissionBean" class="com.ssm.chapter9.pojo.PermissionBean" />

<bean id="role_1" class="com.ssm.chapter9.pojo.Role">
    <property name="roleName" value="高级工程师" />  <!--对应setRoleName(String)-->
    <property name="note" value="重要人员" />        <!--对应setNote(String)-->
    <property name="permissionBean" ref="permissionBean" />
</bean>

元素说明:

  • id : bean的唯一标识。如果不声明,则用”全限定名#{number}”的格式生成
  • class:类的全限定名,指定bean配置的的类。
  • property:定义的类的属性配置。
    • name: 属性名称
    • value: 属性值(基础类型。)
    • ref: 属性值,引用其他bean的id。

集合类型的装配示例:

<bean id="complexAssembly" class="com.ssm.chapter10.pojo.ComplexAssembly">
    <property name="id" value="1" />
    <property name="list"> <!--基础类型的list-->
        <list>
            <value>value-list-1</value>
            <value>value-list-2</value>
            <value>value-list-3</value>
        </list>
    </property>
    <property name="list2"> <!--对象类型的list-->
        <list>
            <ref bean="beanId_1"/>
            <ref bean="beanId_2"/>
        </list>
    </property>

    <property name="map"> <!--基础类型的map-->
        <map>
            <entry key="key1" value="value-key-1" />
            <entry key="key2" value="value-key-2" />
            <entry key="key3" value="value-key-3" />
        </map>
    </property>

    <property name="map2"> <!--对象类型的map-->
        <map>
            <entry key-ref="key_beanId_1" value-ref="value_beanId_1" />
            <entry key-ref="key_beanId_2" value-ref="value_beanId_2" />
            <entry key-ref="key_beanId_3" value-ref="value_beanId_3" />
        </map>
    </property>

    <property name="props">
        <props>
            <prop key="prop1">value-prop-1</prop>
            <prop key="prop2">value-prop-2</prop>
            <prop key="prop3">value-prop-3</prop>
        </props>
    </property>
    <property name="set">
        <set>
            <value>value-set-1</value>
            <value>value-set-2</value>
            <value>value-set-3</value>
        </set>
    </property>
    <property name="array">
        <array>
            <value>value-array-1</value>
            <value>value-array-2</value>
            <value>value-array-3</value>
        </array>
    </property>
</bean>

元素说明:

  • List:List集合
    • <list>...</list>
    • 子元素(基础值):value:设置值
    • 子元素(对象值):ref:设置引用的id
  • Map:Map集合
    • <map>...</map>
    • 子元素(基础值):<entry key="key1" value="value-key-1" />
    • 子元素(对象值):<entry key-ref="key_beanId_3" value-ref="value_beanId_3" />
  • Properties:配置文件类型
    • <props>...</props>
    • 子元素:<prop key="prop2">value-prop-2</prop>
  • Set:Set集合(子元素同list)
    • <set>...</set>
  • array:数组(子元素同list)
    • <array>...</array>

命名空间定义的装配:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:c="http://www.springframework.org/schema/c" <!--引入命名空间的定义-->
    xmlns:p="http://www.springframework.org/schema/p" <!--引入命名空间的定义-->
    xmlns:util="http://www.springframework.org/schema/util" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    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.xsd">  <!--引入util的模板文件-->
    <bean id="role1" class="com.ssm.chapter10.pojo.Role" 
    c:_0="1" c:_1="role_name_1" c:_2="role_note_1" />
    <bean id="role2" class="com.ssm.chapter10.pojo.Role" 
        p:id="2" p:roleName="role_name_2" p:note="role_note_2" />
    <bean id="user1" class="com.ssm.chapter10.pojo.User" 
        p:id="1" p:userName="role_name_1" p:note="user_note_1" />
    <bean id="user2" class="com.ssm.chapter10.pojo.User" 
        p:id="2" p:userName="role_name_2" p:note="user_note_2" />

    <util:list id="list">
        <ref bean="role1" />
        <ref bean="role2" />
    </util:list>

    <util:map id="map">
        <entry key-ref="role1" value-ref="user1" />
        <entry key-ref="role2" value-ref="user2" />
    </util:map>

    <util:set id="set">
        <ref bean="role1" />
        <ref bean="role2" />
    </util:set>

    <bean id="userRoleAssembly" class="com.ssm.chapter10.pojo. UserRoleAssembly"
        p:id="1" p:list-ref="list" p:map-ref="map" p:set-ref="set" />
</beans>

元素说明:

  • c:代表构造器方法的参数,c:_(1,2,3,…N):(第一,第二,第三,。。。第N)个构造器参数
  • p:代表属性的引用,p:[属性名]
  • util:集合类型

###2.2 注解配置
Spring提供了2种方式来让Spring IoC容器发现Bean:

  1. 组件扫描:通过定义资源方式,让Spring IoC容器扫描对应的包,从而把Bean装配进去。
  2. 自动装配: 通过注解定义,使得一些依赖关系可以通过注解完成。

注解及作用:

  • @Component:声明为Bean,可写作:@Component(value="beanName")@Component("beanName"),不设置默认为首字母小写的类名。
  • @Value:类中属性注入的值。
  • @ComponentScan:组件扫描,默认扫描当前包路径下。
    • basePackages:指定扫描包路径下的组件。eg:basePackageClasses = { Role.class, RoleServiceImpl.class }
    • basePackageClasses:指定扫描eg:basePackages = {"com.ssm.chapter10.annotation.pojo","包路径.."}
    • excludeFilters:指定不适合组件扫描的类型。eg:excludeFilters = {@Filter(type = FilterType.REGEX, pattern="类全限定名")}
    • includeFilters:指定哪些类型有资格用于组件扫描。
  • @Autowired:自动装配。为引用对象的属性注入值。
    • eg: @Autowired Role role = null;//会查找容器中对应类型的Bean,然后注入。
    • eg: @Autowired public void setRole(Role role){...}
    • eg: public RoleController(@Autowired RoleService roleService) {...}//构造器装配
  • @Primary:装配优先级设置,设置后存在多个相同类型的Bean,会优先使用设置@Primary的Bean,通过
  • @Qualifier:指定自动装配的具体Bean。消除装配的不确定性
  • @Bean:提供一种注解到方法上的Bean装配到Spring IoC容器中。可以将方法的返回值作为Bean装配到IoC容器中。eg:@Bean(name="beanId")
  • @import:存在多个配置类时使用,导入其他配置类。eg:@Import({AppConfig1.class,AppConfig2.class})
  • @importResource:导入xml配置。eg:@ImportResource({"classpath:spring-dataSource.xml"}),可同时导入多个
    • xml中通过:<import resourse="spring-dataSource.xml"/>引入其他配置文件。
  • @PropertySource:导入properties文件配置。eg:@PropertySource(value = { "classpath:database-config.properties" }, ignoreResourceNotFound = true)
  • @Profile:为一个Bean配置多个不同的环境设置。
  • @Conditional:通过条件配置装配Bean,需要实现Condition接口。eg:@Conditional({DataSourceCondition.class})
  • @Scope:设置Bean的作用域
    • singleton:单例,整个应用只生成一个Bean实例。
    • prototype:原型,通过Spring IoC容器获取Bean是,都会为它创建一个新的实例。
    • session:一个会话一个实例。
    • request:一次请求中创建一个实例。

###3.总结

Spring框架主要是提供一个Spring IoC容器,用于装配和管理各种资源(Bean)。在程序开发中可以便捷的获取指定业务相关的Bean实例,加速开发和减少第三方库集成使用的难度。

END

– Nowy

– 2018.12.09

分享到