在配置文件中定义Bean时,用户不但可以配置Bean的属性值以及相互之间的依赖关系,还可以定义Bean的作用域。作用域将对Bean的生命周期和创建方式产生影响。Spring一般采用scope=“作用域类型”的方式。
Bean作用域类型:
Spirng以容器的方式提供了单实例模式功能,任何POJO无须编写特殊的代码,仅通过配置就可以进行单实例模式。
一般情况下,无状态或者状态不可变的类适合使用单实例模式,不过Spring对此实现了一定的提升。在传统开发中,由于Dao类持有Connection这个非线程安全的变量往往没有采用单实例模式。而在Spring环境下,对于所有的Dao类都可以采用单实例模式,因为Spring利用AOP和LocalThread的功能对非线程安全(或称状态)的变量进行了特殊的处理,使这些非线程安全的类变为线程安全的类。
在默认情况下,Spring的ApplicationContext容器在启动时,自动实例化所有singleton的Bean并缓存在容器中。这样做的好处是,首先对Bean提前实例化可以及早发现配置问题,其次Bean以缓存的方式保存,当运行期用到该Bean的时候就无须再实例化,加快了运行效率。如果用户不希望容器在启动时提前实例化singleton的Bean,可以通过lazy-init属性(懒加载)进行控制。
采用scope=“prototype”指定非单实例作用域的Bean,请看下面的配置:
通过上述配置,boss1、boss2、boss3所引用了都是一个新的实例,每次通过容器的getBean(“car”)方法返回的也是一个新的Car实例。
在默认情况下,Spring容器启动时不实例化prototype的Bean。此外,Spring容器的prototype的Bean交给调用者后,就不再管理Bean的生命周期了。
request作用域的Bean对应一个HTTP请求和生命周期,每次HTTP请求调用到Bean时,Spring都会创建一个新的Bean,直到请求处理完毕才销毁这个Bean。
Bean的作用域横跨整个HTTP Session,Session中所有HTTP请求共享一个Bean,当会话结束后,实例才被销毁
globalSession作用域类似于session作用域,不过仅在Portlet的Web应用中使用。如果不在Portlet应用环境下,globalSession自然就等价于session作用域了。
Spring容器启动成功的三个条件为:Bean定义信息、Bean实现类以及Spring本身。如果采用基于XML的配置,Bean定义信息和Bean实现类本身是分离的,而采用基于注解的配置方式时,Bean定义信息即通过在Bean实现类上标注注解实现。
@Component("car")
public class Car{
.........
}
@Component注解在Car类声明处对类进行标注,它可以被Spirng容器识别,Spring容器自动将POJO转换为容器管理的Bean。
它与以下XML的配置是等效的:
除了@Component以外,Spring提供了三个功能基本和@Component等效的注解,它们分别用于对DAO、Service以及Web层的Controller进行注解,所以这些注解也称为Bean的衍型注解:
之所以要在@Component之外提供这三种特殊的注解,是为了让注解类本身的用途更加清晰化,此外Spring还赋予它们一些特殊的功能。
使用@Autowired进行自动注入
.....
@Service //将UserServer标注为一个服务层的Bean
public class UserService {
@Autowired
private UserDao userDao;
@Autowired
private LoginLogDao loginLogDao;
.....
}
通过使用@Service将UserServer标注为一个服务层的Bean,通过@Autowired注入UserDao和LoginLogDao的Bean。@Autowired默认按类型匹配的方式,在容器查找匹配的Bean,当且仅当一个匹配的Bean时,Spring将其注入到@Autowired标注的变量中。
使用@Qualifier指定注入Bean的名称
如果容器中有一个以上匹配的Bean时,则可以通过@Qualifier注解限定Bean的名称。假如容器中有两个类型为UserDao的Bean,一个名为userDao,另一个名为otherUserDao,则可通过@Qualifier(“userDao”)注入。
.....
@Service //将UserServer标注为一个服务层的Bean
public class UserService {
@Autowired
@Qualifier("userDao")
private UserDao userDao;
@Autowired
private LoginLogDao loginLogDao;
.....
}
如果一个方法拥有多个入参,在默认情况下,Spring自动选择匹配入参类型的Bean进行注入。Spring允许对方法入参标注@Qualifier以指定注入Bean的名称。
@Autowired
public void init(@Qualifier("userDao")UserDao userDao, LogDao logDao){
this.userDao = userDao;
this.logDao=logDao;
}
以上例子中,UserDao的入参注入名为userDao的Bean,而LogDao的入参注入LogDao类型的Bean。