Bean 定义
被称作 bean 的对象是构成应用程序的支柱也是由 Spring IOC 容器管理的。bean 是一个被实例化,组装,并通过 Spring IOC 容器所管理的对象。这些 bean 是由用容器提供的配置元数据创建的,例如:在 XML 的表单中的 定义。
Bean 与 Spring 容器的关系
Bean配置信息定义了Bean的实现及依赖关系,Spring容器根据各种形式的Bean配置信息在容器内部建立Bean定义注册表,然后根据注册表加载、实例化Bean,并建立Bean和Bean的依赖关系,最后将这些准备就绪的Bean放到Bean缓存池中,以供外层的应用程序进行调用。
Bean配置方式
方式一:基于xml配置Bean
基于XML的配置是Spring 2.0以后使用Schema的格式,使得不同类型的配置拥有了自己的命名空间,是配置文件更具扩展性。
图中:
1、默认命名空间:它没有空间名,用于Spring Bean的定义。命名空间的定义分为两个步骤:第一步指定命名空间的名称;第二步指定命名空间的Schema文档样式文件的位置,用空格或回车换行进行分分隔。
2、xsi命名空间:这个命名空间用于为每个文档中命名空间指定相应的Schema样式文件,是标准组织定义的标准命名空间。
3、aop命名空间:这个命名空间是Spring配置AOP的命名空间,是用户自定义的命名空间。
bean基本配置及其属性
<bean id="test_bean" class="com.spring.beans.Person"></bean>
其中:
1、id为这个Bean的名称,通过容器的getBean("test_bean")即可获取对应的Bean,在容器中起到定位查找的作用,是外部程序和Spring IOC容器进行交互的桥梁,id的值必须是唯一的,相当于每个人只能有一个身份证号码一样;若 id 没有指定,Spring 自动将权限定性类名作为 Bean 的名字; id 可以指定多个名字,名字之间可用逗号、分号、或空格分隔。
2、class属性指定了Bean对应的实现类。
bean 定义所支持的属性:
属性 | 描述 |
---|---|
class | 这个属性是强制性的,并且指定用来创建 bean 的 bean 类。 |
name、id | 这个属性指定唯一的 bean 标识符。在基于 XML 的配置元数据中,你可以使用 ID 和/或 name 属性来指定 bean 标识符。 |
scope | 这个属性指定由特定的 bean 定义创建的对象的作用域。 |
constructor-arg | 它是用来注入依赖关系的。 |
properties | 它是用来注入依赖关系的。 |
autowiring mode | 它是用来注入依赖关系的,并会在接下来的章节中进行讨论。 |
lazy-initialization mode | 延迟初始化的 bean 告诉 IoC 容器在它第一次被请求时,而不是在启动时去创建一个 bean 实例。 |
initialization 方法 | 在 bean 的所有必需的属性被容器设置之后,调用回调方法。它将会在 bean 的生命周期章节中进行讨论。 |
destruction 方法 | 当包含该 bean 的容器被销毁时,使用回调方法。它将会在 bean 的生命周期章节中进行讨论。 |
依赖注入的方法:属性注入、构造函数注入、工厂方式注入
方式二:使用注解定义Bean
Spring容器成功启动的三大要件分别是:Bean定义信息、Bean实现类以及Spring本身。如果采用基于XML的配置,Bean定义信息和Bean实现类本身是分离的,而采用基于注解的配置方式时,Bean定义信息即通过在Bean实现类上标注注解实现。
样例代码
package com.spring.beans;
import org.springframework.stereotype.Component;
@Component("userinfo")
public class UserInfo {
}
使用@Component注解在UserInfo类声明处对类进行标注,它可以被Spring容器识别,Spring容器自动将POJO转换为容器管理的Bean。它和以下的XML配置是等效的:
<bean id="userinfo" class="com.spring.beans.UserInfo"/>
除了@Component以外,Spring提供了3个功能基本和@Component等效的注解,它们分别用于对DAO、Service及Web层的Controller进行注解,所以也称这些注解为Bean的衍型注解:(类似于xml文件中定义Bean<bean id=" " class=" "/>
- @Repository:用于对DAO实现类进行标注;
- @Service:用于对Service实现类进行标注;
- @Controller:用于对Controller实现类进行标注;
之所以要在@Component之外提供这三个特殊的注解,是为了让注解类本身的用途清晰化,此外Spring将赋予它们一些特殊的功能。
使用注解配置信息启动spring容器
Spring提供了一个context的命名空间,它提供了通过扫描类包以应用注解定义Bean的方式:
<?xml version="1.0" encoding="UTF-8" ?>
<!--①声明context的命名空间-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd"
>
<!--②扫描类包以应用注解定义的Bean-->
<context:component-scan base-package="com.spring.beans"/>
<bean class="com.spring.beans.UserInfo"></bean>
</beans>
在①处声明context命名空间,在②处即可通过context命名空间的component-scan的base-package属性指定一个需要扫描的基类包,Spring容器将会扫描这个基类包里的所有类,并从类的注解信息中获取Bean的定义信息。
如果仅希望扫描特定的类而非基包下的所有类,你们可以使用resource-pattern属性过滤特定的类,如下所示:
< context:component-scan base-package="com.spring" resource-pattern="bean/*.class"/ >
方式三:基于Java类提供Bean定义
在普通的POJO类中只要标注@Configuration注解,就可以为spring容器提供Bean定义的信息了,每个标注了@Bean的类方法都相当于提供了一个Bean的定义信息。
package com.baobaotao.conf;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
//①将一个POJO标注为定义Bean的配置类
@Configuration
public class AppConf {
//②以下两个方法定义了两个Bean,以提供了Bean的实例化逻辑
@Bean
public UserDao userDao(){
return new UserDao();
}
@Bean
public LogDao logDao(){
return new LogDao();
}
//③定义了logonService的Bean
@Bean
public LogonService logonService(){
LogonService logonService = new LogonService();
//④将②和③处定义的Bean注入到LogonService Bean中
logonService.setLogDao(logDao());
logonService.setUserDao(userDao());
return logonService;
}
}
①处在APPConf类的定义处标注了@Configuration注解,说明这个类可用于为Spring提供Bean的定义信息。类的方法处可以标注@Bean注解,Bean的类型由方法返回值类型决定,名称默认和方法名相同,也可以通过入参显示指定Bean名称,如@Bean(name="userDao").直接在@Bean所标注的方法中提供Bean的实例化逻辑。
在②处userDao()和logDao()方法定义了一个UserDao和一个LogDao的Bean,它们的Bean名称分别是userDao和logDao。在③处,又定义了一个logonService Bean,并且在④处注入②处所定义的两个Bean。
因此,以上的配置和以下XML配置时等效的:
<bean id="userDao" class="com.baobaotao.anno.UserDao"/>
<bean id="logDao" class="com.baobaotao.anno.LogDao"/>
<bean id="logonService" class="com.baobaotao.conf.LogonService"
p:logDao-ref="logDao" p:userDao-ref="userDao"/>
基于java类的配置方式和基于XML或基于注解的配置方式相比,前者通过代码的方式更加灵活地实现了Bean的实例化及Bean之间的装配,但后面两者都是通过配置声明的方式,在灵活性上要稍逊一些,但是配置上要更简单一些。