###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种方式:
- 构造器注入:Spring采用反射的方式,通过使用构造方法来完成注入。
- 设值注入:Spring采用反射的方式,通过获取Java Bean规范的setter方法完成注入。(较为灵活和可读性高)
- 接口注入:从外部注入。(例如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种方式:
- xml配置
- java的接口和类中实现配置(注解配置)
- 隐式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:
- 组件扫描:通过定义资源方式,让Spring IoC容器扫描对应的包,从而把Bean装配进去。
- 自动装配: 通过注解定义,使得一些依赖关系可以通过注解完成。
注解及作用:
- @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:指定哪些类型有资格用于组件扫描。
- basePackages:指定扫描包路径下的组件。eg:
- @Autowired:自动装配。为引用对象的属性注入值。
- eg:
@Autowired Role role = null;
//会查找容器中对应类型的Bean,然后注入。 - eg:
@Autowired public void setRole(Role role){...}
- eg:
public RoleController(@Autowired RoleService roleService) {...}
//构造器装配
- eg:
- @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"/>
引入其他配置文件。
- 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