bean配置有三种方法:

  • 基于xml配置Bean
  • 使用注解定义Bean
  • 基于java类提供Bean定义信息

基于XML配置Bean

Spring Bean的配置 - 图1

Bean 的作用域

当在 Spring 中定义一个 bean 时,你必须声明该 bean 的作用域的选项。例如,为了强制 Spring 在每次需要时都产生一个新的 bean 实例,你应该声明 bean 的作用域的属性为 **prototype**。同理,如果你想让 Spring 在每次需要时都返回同一个bean实例,你应该声明 bean 的作用域的属性为 **singleton**

Spring 框架支持以下五个作用域,分别为singletonprototyperequestsessionglobal session,5种作用域说明如下所示:

作用域 描述
singleton 在spring IoC容器仅存在一个Bean实例,Bean以单例方式存在,默认值
prototype 每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行newXxxBean()
request 每次HTTP请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境
session 同一个HTTP Session共享一个Bean,不同Session使用不同的Bean,仅适用于WebApplicationContext环境
global-session 一般用于Portlet应用环境,该运用域仅适用于WebApplicationContext环境

注意,如果你使用 web-aware ApplicationContext 时,其中后三个是可用的。

singleton 作用域

singleton是默认的作用域,也就是说,当定义 Bean 时,如果没有指定作用域配置项,则 Bean 的作用域被默认为 singleton
当一个bean的作用域为Singleton,那么Spring IoC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。也就是说,当将一个bean定义设置为singleton作用域的时候,Spring IoC容器只会创建该bean定义的唯一实例

Singleton是单例类型,就是在创建起容器时就同时自动创建了一个bean的对象,不管你是否使用,他都存在了,每次获取到的对象都是同一个对象。注意,Singleton作用域是Spring中的缺省作用域。你可以在 bean 的配置文件中设置作用域的属性为 singleton,如下所示:

  1. <!-- A bean definition with singleton scope -->
  2. <bean id="..." class="..." scope="singleton">
  3. <!-- collaborators and configuration for this bean go here -->
  4. </bean>

prototype 作用域

当一个bean的作用域为Prototype,表示一个bean定义对应多个对象实例。
Prototype作用域的bean会导致在每次对该bean请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)时都会创建一个新的bean实例。Prototype是原型类型,它在我们创建容器的时候并没有实例化,而是当我们获取bean的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象。

根据经验,对有状态的bean应该使用prototype作用域,而对无状态的bean则应该使用singleton作用域。

为了定义 prototype作用域,你可以在 bean 的配置文件中设置作用域的属性为 prototype,如下所示:

  1. <!-- A bean definition with singleton scope -->
  2. <bean id="..." class="..." scope="prototype">
  3. <!-- collaborators and configuration for this bean go here -->
  4. </bean>

Bean 的生命周期

理解 Spring bean 的生命周期很容易。当一个 bean 被实例化时,它可能需要执行一些初始化使它转换成可用状态。同样,当 bean 不再需要,并且从容器中移除时,可能需要做一些清除工作。
《Sping实战》提到的典型的声明周期过程:
Spring Bean的配置 - 图2

  1. Spring对Bean进行实例化(相当于程序中的new Xx())
  2. Spring将值和Bean的引用注入进Bean对应的属性中
  3. 如果Bean实现了BeanNameAware接口,Spring将Bean的ID传递给setBeanName()方法(实现BeanNameAware主要是为了通过Bean的引用来获得Bean的ID,一般业务中是很少有用到Bean的ID的)
  4. 如果Bean实现了BeanFactoryAware接口,Spring将调用setBeanDactory(BeanFactory bf)方法并把BeanFactory容器实例作为参数传入。(实现BeanFactoryAware主要目的是为了获取Spring容器,如Bean通过Spring容器发布事件等)
  5. 如果Bean实现了ApplicationContextAwaer接口,Spring容器将调用setApplicationContext(ApplicationContext ctx)方法,把bean所在的应用上下文作为参数传入。(作用与BeanFactory类似都是为了获取Spring容器,不同的是Spring容器在调用setApplicationContext方法时会把它自己作为setApplicationContext的参数传入,而Spring容器在调用setBeanDactory前需要程序员自己指定(注入)setBeanDactory里的参数BeanFactory)
  6. 如果Bean实现了BeanPostProcess接口,Spring将调用它们的postProcessBeforeInitialization(预初始化)方法。(作用是在Bean实例创建成功后进行增强处理,如对Bean进行修改,增加某个功能)
  7. 如果Bean实现了InitializingBean接口,Spring将调用它们的afterPropertiesSet方法,作用与在配置文件中对Bean使用init-method声明初始化的作用一样,都是在Bean的全部属性设置成功后执行的初始化方法。
  8. 如果Bean实现了BeanPostProcess接口,Spring将调用它们的postProcessAfterInitialization(后初始化)方法。(作用与6的一样,只不过6是在Bean初始化前执行的,而这个是在Bean初始化后执行的,时机不同 )
  9. 经过以上的工作后,Bean将一直驻留在应用上下文中给应用使用,直到应用上下文被销毁
  10. 如果Bean实现了DispostbleBean接口,Spring将调用它的destory方法,作用与在配置文件中对Bean使用destory-method属性的作用一样,都是在Bean实例销毁前执行的方法。

示例:

  1. package com.haan.beanlifecycle;
  2. import org.springframework.beans.BeansException;
  3. import org.springframework.beans.factory.*;
  4. import org.springframework.beans.factory.config.BeanPostProcessor;
  5. import org.springframework.context.ApplicationContext;
  6. import org.springframework.context.ApplicationContextAware;
  7. /**
  8. * @Desc
  9. * @Created By liukuihan
  10. * @date on 2020/5/23
  11. */
  12. public class LiftCycleTest implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, BeanPostProcessor, InitializingBean,DisposableBean {
  13. private String message;
  14. public LiftCycleTest(){
  15. System.out.println("实例化LiftCycleTest...");
  16. }
  17. public void setMessage(String message) {
  18. this.message = message;
  19. System.out.println("设置LiftCycleTest的message属性..."+message);
  20. }
  21. @Override
  22. public void setBeanName(String s) {
  23. System.out.println("Bean(LiftCycleTest)的bean Id="+s);
  24. }
  25. @Override
  26. public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
  27. System.out.println(beanFactory.toString());
  28. }
  29. @Override
  30. public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  31. System.out.println(applicationContext.toString());
  32. }
  33. @Override
  34. public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  35. System.out.println("初始化bean之前...");
  36. return null;
  37. }
  38. @Override
  39. public void afterPropertiesSet() throws Exception {
  40. System.out.println("Bean的全部属性设置成功...");
  41. }
  42. @Override
  43. public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  44. System.out.println("初始化bean之后...");
  45. return null;
  46. }
  47. @Override
  48. public void destroy() throws Exception {
  49. System.out.println("bean被摧毁了");
  50. }
  51. public void customerInit(){
  52. System.out.println("定制初始化方法执行了...");
  53. }
  54. public void customerDestroy(){
  55. System.out.println("定制bean摧毁方法执行了...");
  56. }
  57. }

bean.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  5. <bean class="com.haan.HelloWord" id="helloWord"></bean>
  6. <bean class="com.haan.beanlifecycle.LiftCycleTest" id="liftCycleTest" init-method="customerInit" destroy-method="customerDestroy">
  7. <property name="message" value="testssssssss"/>
  8. </bean>
  9. </beans>

main

  1. public class Main {
  2. public static void main(String[] args) {
  3. // BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("bean.xml")); //<1>
  4. //
  5. // HelloWord helloWord = (HelloWord) beanFactory.getBean("helloWord"); //<2>
  6. // helloWord.sayHello(); //<3>
  7. //
  8. // ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
  9. // HelloWord helloWord = (HelloWord) context.getBean("helloWord");
  10. // helloWord.sayHello();
  11. AbstractApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
  12. context.registerShutdownHook();
  13. }
  14. }
  1. 实例化LiftCycleTest...
  2. 设置LiftCycleTestmessage属性...testssssssss
  3. Bean(LiftCycleTest)的bean Id=liftCycleTest
  4. org.springframework.beans.factory.support.DefaultListableBeanFactory@4cb2c100: defining beans [helloWord,liftCycleTest]; root of factory hierarchy
  5. org.springframework.context.support.ClassPathXmlApplicationContext@1a86f2f1, started on Sat May 23 11:33:23 CST 2020
  6. Bean的全部属性设置成功...
  7. 定制初始化方法执行了...
  8. 初始化bean之前...
  9. 初始化bean之后...
  10. bean被摧毁了
  11. 定制bean摧毁方法执行了...


使用注解定义Bean

基于java类提供Bean定义信息