(三)Bean生命周期

1 Bean注册

应用启动实质是调用Spring容器启动方法扫描配置加载bean到Spring容器中、同时启动内置的Web容器的过程,具体分析如下:

@SpringBootApplication注解在主类上,用于注入对象到ioc容器中,方便程序中提取对象使用。如下所示:

@SpringBootApplication
public class TomcatdebugApplication {
     public static void main(String[] args) {
         SpringApplication.run(TomcatdebugApplication.class, args);
     } 
}

该注解包括@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan三个注解。

(1)@ComponentScan

  Spring有四大注解:@Respository、@Service、@Component、@Controller用来定义bean,该注解就是用来自动扫描这些注解标识的类,最终生成ioc容器里的bean,以提供一个Spring的上下文环境。默认情况下,它扫描的范围是run方法中的Class对象对应的包路径下的所有文件,所以最好将该启动类放到根包路径下。

  需要说明的是,这四大注解是没什么本质区别的,当不指定bean时,默认以类名首字母小写作为Ioc管理的该类的对象,当指定bean时,会以指定bean的名字注册实例。对象注入方式完全一致,之所以区分为四层只是为了更好的区分各自的功能。

(2)@EnableAutoConfiguration

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({EnableAutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class<?>[] exclude() default {};

    String[] excludeName() default {};
}

其中最关键的要属@Import({EnableAutoConfigurationImportSelector.class}),借助EnableAutoConfigurationImportSelector,@EnableAutoConfiguration可帮助SpringBoot应用将所有符合条件的@Configuration配置都加载到当前SpringBoot创建并使用的Ioc容器中。

(3)@SpringBootConfiguration注解  

  来源:该注解继承自@Configuration,二者功能也一致,提供一种新的bean注入方式。

  作用:标注当前类是配置类,将当前类声明的一个或多个@Bean注解标记方法的实例注册到Spring容器中,并且实例名就是方法名。

 @SpringBootConfiguration
  public class Config {
      @Bean  //注入后的实例名为createMap
      public Map createMap(){
          Map map = new HashMap();
          map.put("username","gxz");
          map.put("age",27);
          return map;
      }
 }

 

2 Bean使用

2.1 单例或工厂

注入对象时,用@Scope注解可声明bean的生成方式,其中,Scope常用值如下:

 

Scope

Description

作用范围

singleton

默认值,Ioc容器只存在单例

所有Spring应用

prototype

每当从Ioc容器中取出一个bean,则创建一个新的bean

所有Spring应用

 

@Component
@Scope("prototype")
public class ScopeBean {
    ...
}

 

2.2 bean提取

对象的注入有多种方式,但提取时都是使用@Autowired和@Resource提取,并且默认bean是单例。因此关于这两个注解的解析很重要。

2.1.2 @Resource

@Resource是Java自带注解,该注解有两个属性比较重要,包括name和type,SpringBoot将该注解的name属性解析成bean的名字,type属性则解析成bean的类型。@Resource的装配顺序:

(1)如果同时指定了name属性和type属性,那么Spring将从容器中找唯一匹配的bean进行装配,找不到则抛异常。

(2)如果指定了name属性值,则从容器中查找名称匹配的bean进行装配,找不到或者找到多个都会抛异常。

(3)如果指定了type属性值,则从容器中查找类型匹配的唯一的bean进行装配,找不到或者找到多个都会抛出异常。

(4)如果都不指定,则会自动按照byName方式进行装配,如果没有装配,则回退到一个原始类型进行匹配,如果匹配则自动装配。

2.1.3 @Autowired

@Autowired是spring的注解,该注解只根据type来进行注入,不会去匹配name,如果涉及到type无法辨别注入对象,那就需要Qualifier注解或Primary注解指定bean名一起注释。并且默认情况下,它要求依赖对象必须存在,如果允许null值,可以设置它required为false。

 

3 Bean构造与析构

 由于前面已经解析了bean注册、销毁时机,因此这里解析的Bean的生命周期过程只包含bean构造和析构过程:

【初始化顺序】:构造函数 --> @PostConstruct --> afterProppertiesSet(重载) --> 自定义initMethod方法 -->   [bean初始化完成] ---> postProcessBeforeInitialization(重载)  --> postProcessAfterInitialization(重载) --> [注册到Ioc容]

【销毁顺序】: @PreDestory --> destory(重载) --> 自定义destoryMethod --> [bean销毁]

【详解相关接口】:

 afterPropertiesSet:初始化bean的时候执行,可以针对某个具体的bean进行配置

 postProcessBeforeInitalization:该方法会在Bean构造完执行,该方法接收两个参数:

  (1)Object bean: 刚刚由Spring实例化出来的bean

  (2)String beanName: 在Spring配置的元数据bean的名称

 该方法的返回值会被Spring容器作为处理后的Bean注册到Ioc容器中并覆盖原来的Bean。其中,测试Demo如下所示:

// 功能类
public class Car implements InitializingBean, DisposableBean, BeanPostProcessor {
  
    // 构造(顺序定义)

    public Car() {
        System.out.println("Car 创建");
    }

    @PostConstruct
    public void postConstructTest() {
        System.out.println(" .. @PostConstruct .. ");
    }

    @Override
    public void afterPropertiesSet() {
        System.out.println(" .. InitializingBean .. ");
    }

    public void initTest() {
        System.out.println(" .. init-method .. ");
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName)
            throws BeansException {

        System.out.println(" .. postProcessBeforeInitialization .. ");

        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {

        System.out.println(" .. postProcessAfterInitialization .. ");

        return bean;
    }

    // 销毁(顺序定义)

    @PreDestroy
    public void preDestroyTest() {
        System.out.println(" .. @PreDestroy .. ");
    }

    @Override
    public void destroy() {
        System.out.println(" .. DisposableBean .. ");
    }

    public void detoryTest() {
        System.out.println(" .. destory-method .. ");
    }
    
}

//注册
@Configuration
public class MainConfigOfLifeCycle {
 
    @Bean(initMethod="initTest", destroyMethod="detoryTest")
    public Car car() {
        return new Car();
    }
}

// 测试
public class IOCTest_LifeCycle {
 
    @Test
    public void test01() {
        // 1. 创建IOC容器
        AnnotationConfigApplicationContext applicationContext = 
            new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
        System.out.println("容器创建完成");
 
        // 关闭容器
        applicationContext.close();
    }
}

要控制bean对象的构造和销毁过程,可结合上述的分析进行控制。

posted @ 2020-05-04 11:48  FCity  阅读(193)  评论(0编辑  收藏  举报