第四章 Spring Bean基础.pdf

Spring Bean基础

1.定义Spring Bean

BeanDefinition是Spring Framework中定义Bean配置的元信息接口,包含:

  • Bean的类名
  • Bean的行为配置,如作用域、自动绑定的模式、生命周期回调等
  • 其他Bean的引用,又可称为合作者(Colloborators)或者依赖(Dependency)
  • 配置设置,比如Bean属性(Properties)

    2.BeanDefinition元信息

BeanDefinition元信息
属性 说明
Class Bean全类名,必须是具体类,不能使用抽象类或接口
Name Bean的名称或ID
Scope Bean的作用域(如Sigleton、Prototype)
Constructor arguments Bean构造器参数(用于依赖注入)
Properties Bean的属性设置(用于依赖注入)
Autowiring mode Bean自动绑定模式(如:通过名称 ByName)
Lazy initislization mode Bean延迟初始化模式(延迟和非延迟)
Initialization method Bean 初始化回调方法名称
Destruction method Bean销毁回调方法名称

BeanDefinition构建:

  • 通过BeanDefinitionBuilder
  • 通过AbstractBeanDefinition以及派生类 | BeanDefinition接口及其实现类 | | —- | | image.png |
  1. public class BeanDefinitionDemo {
  2. public static void main(String[] args) {
  3. //1、通过 BeanDefinitionBuilder 构建 BeanDefinition
  4. BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User.class);
  5. beanDefinitionBuilder
  6. .setScope("singleton")
  7. .addPropertyValue("id", 1)
  8. .addPropertyValue("name", "黑岩射手");
  9. AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
  10. //2、通过AbstractBeanDefinition以及派生类
  11. AbstractBeanDefinition abstractBeanDefinition = new GenericBeanDefinition();
  12. abstractBeanDefinition.setBeanClass(User.class);
  13. abstractBeanDefinition.setScope("singleton");
  14. abstractBeanDefinition.setPropertyValues(new MutablePropertyValues().add("id", 2).add("name", "Dead Master"));
  15. }
  16. }

3.命名Spring Bean

Bean的名称

  • 每个Bean拥有一个或多个标识符(identifiers),这些标识符在Bean所在的容器必须是唯一的。通常,一个Bean仅有一个标识符,如果需要额外的,可考虑使用别名(Alias)来扩充。
  • 在基于XML的配置元信息中,开发人员可用id或者name属性来规定Bean的标识符。通常Bean的标识符由字母组成,允许出现特殊字符。如果要想引入Bean的别名的话,可在name属性使用半角逗号(“,”)或分号(“;”)来间隔。
  • Bean的id或name属性并非必须制定,如果留空的话,容器会为Bean自动生成一个唯一的名称。Bean的命名尽管没有限制,不过官方建议采用驼峰的方式,更符合Java的命名约定。

Bean的名称命名底层实现
Bean名称生成器(BeanNameGenerator)由Spring Framework 2.0.3引入,框架內建两种实现:

  • DefaultBeanNameGenerator:默认通用BeanNameGenerator实现
  • AnnotationBeanNameGenerator:基于注解扫描的BeanNameGenerator实现,起始于Spring | BeanNameGenerater接口及其实现 | | —- | | image.png |

4.SpringBean的别名

Bean别名(Alias)的价值

  • 复用现有的BeanDefinition
  • 更具有场景化的命名方法,比如:
    • ```xml

  1. ```java
  2. public class BeanAliasDemo {
  3. public static void main(String[] args) {
  4. ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:META-INF/spring-bean-definition.xml");
  5. // 根据Bean别名查找Bean
  6. User blackRockShooter = (User) applicationContext.getBean("blackRockShooter");
  7. // 根据Bean名称查找Bean
  8. User user = (User) applicationContext.getBean("user");
  9. System.out.println(blackRockShooter==user); //true
  10. }
  11. }

5.注册Spring Bean

BeanDefinition注册

  • XML配置元信息
  • Java注解配置元信息
    • @Bean
    • @Component
    • @Import
  • Java API配置元信息
    • 命名方式:BeanDefinitionRegistry#registerBeanDefinition(String,BeanDefinition)
    • 非命名方式:
      • BeanDefinitionReaderUtils#registerWithGeneratedName(AbstractBeanDefinition,BeanDe
        finitionRegistry)
    • 配置类方式:AnnotatedBeanDefinitionReader#register(Class…) ```java /**
  • {@link Import}注解注册Bean */ @Import(AnnotationBeanDefinitionDemo.Config.class) public class AnnotationBeanDefinitionDemo {

    public static void main(String[] args) {

      AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
    
      applicationContext.register(Config.class);
    
    AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(User.class)
            .addPropertyValue("id", 1)
            .addPropertyValue("name", "逢坂大河")
            .getBeanDefinition();
    // java API 方式注册Bean —— 命名方式
    applicationContext.registerBeanDefinition("tiger", beanDefinition);

    // java API 方式注册Bean —— 非命名方式
    BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, applicationContext);

    // 配置类方式 AnnotatedBeanDefinitionReader#registerBean
    AnnotatedBeanDefinitionReader annotatedBeanDefinitionReader = new AnnotatedBeanDefinitionReader(applicationContext);
    annotatedBeanDefinitionReader.registerBean(Config.class);

    // 启动容器
    applicationContext.refresh();
    applicationContext.getBeansOfType(User.class).forEach((beanName, user) -> System.out.println(beanName + " : " + user));

    System.out.println(applicationContext.getBean(Config.class).getUser(3, "魔法小樱"));

}

/**
 * {@link Component} 注解注册Bean
 */
@Component
public static class Config {

    /**
     * {@link Bean} 注解方式注册Bean
     */
    @Bean
    public User user() {
        return new User(2, "black-rock-shooter");
    }

    public User getUser(int id, String name) {
        return new User(id, name);
    }
}

} ``` 外部单例对象注册

  • Java API配置元信息

    • SingletonBeanRegistry#registerSingleton

      6.实例化Spring Bean

      Bean实例化(Instantiation)
  • 常规方式

    • 通过构造器(配置元信息:XML、Java注解和Java API)
    • 通过静态工厂方法(配置元信息:XML和Java API)
    • 通过Bean工厂方法(配置元信息:XML和Java API)
    • 通过FactoryBean(配置元信息:XML、Java注解和Java API)
  • 特殊方式

    • 通过ServiceLoaderFactoryBean(配置元信息:XML、Java注解和Java API)
    • 通过AutowireCapableBeanFactory#createBean(java.lang.Class, int, boolean)
    • 通过BeanDefinitionRegistry#registerBeanDefinition(String,BeanDefinition)

      7.初始化Spring Bean

      Bean初始化(Initialization)
  • @PostConstruct标注方法

  • 实现InitializingBean接口的afterPropertiesSet()方法
  • 自定义初始化方法
    • XML配置:
    • Java注解:@Bean(initMethod=”init”)
    • Java API:AbstractBeanDefinition#setInitMethodName(String)

初始化回调方法执行顺序:

  1. 调用@PostConstruct注释的方法
  2. 调用实现InitializingBean回调接口定义的afterPropertiesSet()方法
  3. 调用一个自定义配置的init()方法

    8.延迟初始化Spring Bean

    Bean延迟初始化(Lazy Initialization)
  • XML配置:
  • Java注解:@Lazy(true

容器启动时,会实例化所有非延迟初始化的单例Bean
image.png

9.销毁Spring Bean

Bean销毁(Destroy)

  • @PreDestroy标注方法
  • 实现DisposableBean接口的destroy()方法
  • 自定义销毁方法
    • XML配置:
    • Java注解:@Bean(destroy=”destroy”)
    • Java API:AbstractBeanDefinition#setDestroyMethodName(String

销毁回调方法执行顺序:

  1. 调用@PreDestroy注释的方法
  2. 调用实现DisposableBean回调接口的destroy()方法
  3. 调用自定义配置的destroy()方法

    10.垃圾回收Spring Bean

    Bean垃圾回收(GC)

  4. 关闭Spring容器(应用上下文)

  5. 执行GC
  6. Spring Bean覆盖的finalize()方法被回调

    11.面试题精选

  • 如何注册一个Spring Bean?

答:通过BeanDefinition和外部单体对象来注册

  • 什么是Spring BeanDefinition?

BeanDefinition是Spring Framework中定义Bean配置的元信息接口,包含:

  • Bean的类名
  • Bean的行为配置,如作用域、自动绑定的模式、生命周期回调等
  • 其他Bean的引用,又可称为合作者(Colloborators)或者依赖(Dependency)
  • 配置设置,比如Bean属性(Properties)
    • Spring容器是怎样管理注册Bean

IoC配置元信息读取和解析、依赖查找和注入以及Bean生命周期等。