回炉Spring--容器及Bean生命周期

一、Spring容器:

  在基于Spring的应用中,你的应用对象生存于Spring容器(container)中,Spring容器负责创建对象,装配它们,配置它们并管理它们的整个生命周期,从生存到死亡。(在这里,可能就是从new()到finalize())。

  容器是Spring框架的核心。Spring容器使用DI(依赖注入)管理构成应用的组件,它会创建相互协作的组件之间的关联。毫无疑问,这些对象更简单干净,更易于理解,更易于重用并且更易于进行单元测试。

 

 Spring自带了多种类型的应用上下文:

  AnnotationConfigApplicationContext: 从一个或多个基于Java的配置类中加载Spring应用上下文。

  AnnotationConfigWebApplicationContext: 从一个或多个基于Java的配置类中加载Spring Web应用上下文。

  ClassPathXmlApplicationContext: 从类路径下的一个或多个XML配置文件中加载上下文定义, 把应用上下文的定义文件作为类资源。

  FileSystemXmlapplicationcontext: 从文件系统下的一个或多个XML配置文件中加载上下文定义。

  XmlWebApplicationContext: 从Web应用下的一个或多个XML配置文件中加载上下文定义。

 

  无论是从哪里装载应用上下文,将bean加载到bean工厂的过程都是类似的。

如果你想从Java配置类中加载应用上下文, 那么可以使用AnnotationConfigApplicationContext,来启动Spring容器

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(xxxConfig.class); // 多个Java配置类逗号隔开

  在这里没有指定加载Spring应用上下文所需的XML文件, AnnotationConfigApplicationContext通过一个配置类加载bean。

  应用上下文准备就绪之后, 我们就可以调用上下文的getBean()方法从Spring容器中获取bean。

 

 Spring容器的一些疑问?

  1、BeanFactory和FactoryBean的区别

    BeanFactory是IOC容器的核心接口,ApplicationContext的父类。Spring使用BeanFactory来实例化、配置和管理bean,采用延迟加载的方式来注入bean,只有在getBean的时候才去加载创建bean

    FactoryBean是创建bean的工厂,通过自定义类实现FactoryBean<T>接口,实现其getObject()方法创建bean对象,在配置文件中使用FactoryBean创建bean对象

 

  2、BeanFactory和ApplicationContext的区别

    ApplicationContext是完整的IOC容器,其由BeanFactory派生而来,具有BeanFactory的所有功能,可以通过配置实现,且额外提供了messageSource,资源访问,aop和web应用,加载多种应用上下文。

并可在启动的时候一次性创建所有需要的单实例bean

 

 

 

二、Spring注解驱动开发

使用Java配置类代替XML配置文件来装配bean:

import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.Scope;

/**
 * Spring 基于Java类注解形式的配置
 *
 * @Configuration :使Spring容器知道这是一个配置类
 * @ComponentScan :启用组件扫描,默认扫描本文件所在的包及其子包下声明了@Component注解的类,并在Spring容器中为其创建一个bean,value属性指定要扫描的包
 *      includeFilters 指定扫描的时候只需要包含哪些组件
 *      excludeFilters 指定扫描的时候按照什么规则排除那些组件,如:
 *          excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Controller.class):排除Controller注解的类
 * @PropertySource :使用@PropertySource读取外部配置文件中的k/v保存到运行的环境变量Environment中;加载完外部的配置文件以后使用@Value("${key}" 取出配置的值。
 *  也可以用Spring容器获取Environment变量,然后getProperty获取到配置的value。如:
 *      ConfigurableEnvironment environment = context.getEnvironment(); 
 *      String name = environment.getProperty("name");
 *
 * @Import(xxx.class) :快速给容器中导入一个组件,即将组件注册到Spring容器中; 注册到容器的bean的id为导入类的全限定名
 *
 */
@Import(Teacher.class)
@Configuration
@ComponentScan(value = {"com.yang.config", "com.yang.service"})
@PropertySource(value = {"classpath:/config.properties"})
public class ApplicationContextConfig {

    /**
     * 手动向Spring容器中注册一个bean
     * 默认作用域是单例的,bean的类型为方法的返回值,bean的id为方法名,也可以使用@Bean的name属性指定bean的名称。
     *
     * @Scope :bean的作用域,取值范围:
     *      ConfigurableBeanFactory#SCOPE_PROTOTYPE singleton   单例,默认,Spring容器启动就会创建对象并放在容器中,以后每次获取都去map缓存中取
     *      ConfigurableBeanFactory#SCOPE_SINGLETON prototype   原型/多例,Spring容器启动时并不会去创建对象,每次获取的时候都回去创建一个新的对象
     *      org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST request 同一个请求创建一个对象
     *      org.springframework.web.context.WebApplicationContext#SCOPE_SESSION session 同一个session创建一个对象      
     *
     *
     * @Lazy :即懒加载,针对单实例作用域的bean,默认值为true,即Spring容器启动的时候不创建,第一次调用的时候才去创建
     *      不使用@Lazy注解的话则不是懒加载,Spring容器启动的时候就创建bean
     *
     * @Conditional :按照一定的条件进行判断,满足条件给容器中注册bean;若用在配置类上,则只有满足条件,此配置类上的所有的bean才会去Spring容器中去注册
     *      使用场景如只在linux系统中才创建bean
     *      Class<? extends Condition>[] value(); 接收一个实现Condition接口的类的class对象,需要自定义类实现Condition接口在matches方法中实
     *           现具体判断逻辑,返回true代表符合条件
     *
     */
    @Lazy(value = false)
    @Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
    @Bean
    public Person person() {
        return new Person("yangyongjie");
    }


    /**
     * 工厂bean方式注册bean到Spring容器中
     * bean的id同样为 方法名,注册到Spring容器中的bean为getObject方法返回的对象
     */
    @Bean
    public StudentFactoryBean studentFactoryBean(){
        return new StudentFactoryBean();
    }

    /**
     * Student类的工厂bean
     */
    static class StudentFactoryBean implements FactoryBean<Student> {

        /**
         * 返回Student对象
         */
        @Override
        public Student getObject() throws Exception {
            return new Student();
        }

        @Override
        public Class<?> getObjectType() {
            return Person.class;
        }

        @Override
        public boolean isSingleton() {
            //false 多例 true 单例
            return false;

        }
    }

}

 

 

 Java类注解形式配置的一些疑问?

  1、JavaConfig方式创建bean的时候如何实现注入依赖?

    1)直接引用创建依赖bean的方法,使用的是带参构造器。但是这种引用并不会创建多个依赖bean的对象,因为Spring将会拦截对它的调用,并确保直接返回该方法所创建的bean,而不是每次都对其进行实际的调用。

    2)将依赖的bean类型当成@Bean所在方法的一个参数。当Spring调用@Bean注解所在方法创建bean的时候,会自动装配一个参数类型bean到方法之中,然后方法体就可以按照合适的方式来使用它。

      这种方式不会像方式1那样要求将依赖bean的声明和当前bean在同一个配置类之中,甚至不要求依赖bean必须在JavaConfig类中声明。

        疑问,若有多个同一类型的依赖bean,Spring怎么选择装配?

        答案:先参数类型,后参数名称。源码在DefaultListableBeanFactory#doResolveDependency:1213

 

  2、Spring为啥把bean默认设计成单例?

    优势:为了提高性能

      1、减少创建新实例的消耗

      2、减少JVM垃圾回收

      3、可以快速获取到bean

    劣势:不能做到线程安全,bean如果是有状态的话在并发环境下线程不安全

 

  3、@PropertySource("classpath:/config.properties") 是在什么时机解析配置文件的?

    步骤如下:

addPropertySource(ConfigurationClassParser.java:512) // 将resource对象解析成PropertySource对象并添加到Spring容器中的environment对象中。并将配置文件名添加到propertySourceNames集合中
processPropertySource(ConfigurationClassParser.java:463) // 处理属性配置文件,将自定义的属性配置文件解析成Resource对象
doProcessConfigurationClass(ConfigurationClassParser.java:280) // 如果配置类上有@PropertySource,那么处理属性文件,后面还会处理其他注解,如@ComponentScan等
processConfigurationClass(ConfigurationClassParser.java:250) // 处理Java配置类
processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:323) // 处理配置类中bean的定义信息
postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:247) // 调用postProcessBeanDefinitionRegistry方法
invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:746) // 调用BeanDefinitionRegistryPostProcessor(BeanFactroyPostProcessor的子接口)类型的后置处理器
invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:746) // 调用BeanFactory的后置处理器

 

 

 

 总结:

   向Spring容器中注册组件(bean)的四种方式:

    1、包扫描+组件标注注解(@Component、@Controller、@Service、@Repository)

    2、@Bean:适合导入第三方包里面的组件

    3、@Import:快速给容器中导入一个组件

      ①:@Import(要导入的组件的class对象),容器中就会自动注册这个bean,名称是全类名(com.yang.service.TestService)

      ②:@Import(ImportSelector.class),一个ImportSelector接口的实现类,在重写的selectImports方法中返回需要导入的组件的全类名数组

      ③:@Import(ImportBeanDefinitionRegistrar.class)手动注册bean到容器中(在ImportBeanDefinitionRegistrar中使用BeanDefinitionRegistry的registerBeanDefinition方法手动注册)

        BeanDefinitionRegistry:接口,提供往Spring容器中注册bean,移除bean,获取容器中所有注册了的bean和判断Spring容器中是否注册了某个bean

    4、使用Spring提供的 FactoryBean(工厂Bean),与普通bean不同的是,普通bean是调用其无参构造器去创建对象然后注册到容器中,FactoryBean是调用其 T getObject()方法,将返回的对象注册到Spring容器中

      ①:Spring容器中注册的是FactoryBean getObject返回的对象,bean的id同样是方法名,如:personFactoryBean

      ②:要获取FactoryBean本身,FactoryBean本身注册到Spring容器中的id为 “&+bean名称”,如&personFactoryBean

 

 

  扩展

    手动干预一个bean比另一个bean先加载,可使用@DependsOn(value = {"beanName1","beanName2"})

    作用:@DependOn注解指定当前bean所依赖的bean。任何指定的bean都保证由容器在此bean之前创建。

    使用场景:在一个bean没有通过属性或构造函数参数显式地依赖另一个bean,而是依赖于另一个bean初始化的副作用的情况下,不经常使用

    用法:@DependOn注解可用于@Component注解的类上,或@Bean注解的方法上

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DependsOn {

    String[] value() default {};

}

 

    

 

 

三、Spring容器中Bean的生命周期

  bean创建——属性赋值——初始化——销毁

 

  Spring容器管理bean的生命周期

    ①:若是单例的bean,在Spring容器的启动后先创建对象,然后初始化,容器关闭的时候销毁bean

    ②:若是多实例的bean,Spring容器在每次获取bean的时候才去创建对象,然后初始化,但是Spring容器关闭时并不会去销毁bean,需要手动去销毁

 

  bean装配到Spring容器中的一个典型的生命周期过程:

    ①:Spring容器对bean进行实例化

    ②:Spring将值和bean的引用注入到bean对应的属性中

    ③:如果bean实现了BeanNameAware接口,Spring将bean的ID传递给setBeanName()方法

    ④:如果bean实现了BeanFactoryAware接口,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入

    ⑤:如果bean实现了ApplicationContextAware接口,Spring将调用setApplicationContext()方法,将bean所在的应用上下文的引用传进来

    ⑥:遍历容器中BeanPostProcessor接口的实现bean,调用它们的postProcessBeforeInitialization()方法

    ⑦:如果bean实现了InitializingBean接口,Spring将调用它们的afterPropertiesSet()方法。类似的,如果bean使用init-method声明了初始化方法,该方法也会被调用

    ⑧:遍历容器中BeanPostProcessor接口的实现bean,调用它们的postProcessAfterInitialization()方法

    ⑨:此时bean已经准备就绪,可以被应用程序使用了,它们将一直驻留在应用上下文中,直到该应用上下文被销毁

    ⑩:如果bean实现了DisposableBean接口,Spring将调用它的destory()接口方法。同样,如果bean使用destory-method声明了销毁方法,该方法也会被调用。

 

  bean初始化和销毁的四种方式:

    1、指定在bean中自定义初始化和销毁方法,通过@Bean注解指定initMethod和destroyMethod

      如:@Bean(initMethod = "customInit",destroyMethod = "customDestory")

    2、指定在bean中自定义初始化和销毁方法,然后使用javax提供的注解

      @PostConstruct标注在bean的初始化方法上,将在bean创建并属性赋值完成,调用此方法

      @PreDestroy标注在bean的销毁方法上,将在容器销毁对象之前调用

    3、通过使Bean实现InitializingBean和DisposableBean接口,在重写的afterPropertiesSet和destroy方法实现初始化和销毁逻辑

    4、bean的后置处理器,实现BeanPostProcessor接口,在bean的初始化前后做一些工作

    针对全局的bean,如果一个bean实现了BeanPostProcessor接口,那么容器中其他所有bean(只针对单例的bean)在初始化方法执行之前都会调用其postProcessBeforeInitialization方法,在初始化方法执行之后都会调用其postProcessAfterInitialization方法

      postProcessBeforeInitialization:在任何初始化方式之前调用(在PostConstruct、afterPropertiesSet、initMethod 这些初始化之前调用)

      postProcessAfterInitialization:在任何初始化方式之后调用(在PostConstruct、afterPropertiesSet、initMethod 这些初始化之后调用)

     因此bean在初始化前后会调用所有实现了BeanPostProcessor接口的bean的postProcessBeforeInitialization和postProcessAfterInitialization方法。

 

    如果四种方式都写了,那么执行顺序为:

    ①:constructor  创建bean实例

    ②:postProcessBeforeInitialization  BeanPostProcessor的初始化前置方法

    ③:PostConstruct  javax注解定义的初始化方法

    ④:afterPropertiesSet  实现InitializingBean接口的初始化方法

    ⑤:initMethod   @Bean注解上自定义的初始化方法

    ⑥:postProcessAfterInitialization  BeanPostProcessor的初始化后方法

    ⑦:PreDestroy  javax注解定义的销毁方法

    ⑧:destroy  实现DisposableBean接口的销毁方法

    ⑨:destroyMethod   @Bean注解上自定义的销毁方法

 

    即初始化和销毁的执行顺序都是:BeanPostProcessor——> PostConstruct/PreDestroy——>InitializingBean/DisposableBean——>@Bean(initMethod /destroyMethod )

 

 

 

四、从源码看bean创建初始化生命周期

 

      MyBeanPostProcessor.postProcessAfterInitialization(MyBeanPostProcessor.java:20) // 执行某个bean后置处理器的postProcessAfterInitialization方法
      AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:437) // 应用并执行所有的bean后置处理器的postProcessAfterInitialization方法
      at com.yang.domain.Teacher.afterPropertiesSet(Teacher.java:26) // bean初始化
      at com.yang.domain.Teacher.postConstruct(Teacher.java:40) // bean自定义初始化方法
      at sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java:-1)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:498)
      InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:389)
      InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:333) //在这个方法中执行自定义的bean的初始化方法,注意:这也是通过后置处理器完成的
      InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:157) // 执行具体某个bean后置处理器的postProcessBeforeInitialization方法
      AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:422) // 应用并执行所有的bean后置处理器的postProcessBeforeInitialization方法
      AbstractAutowireCapableBeanFactory.invokeAwareMethods(AbstractAutowireCapableBeanFactory.java:1808) // 若bean实现了BeanNameAware、BeanClassLoaderAware、BeanFactoryAware接口则调用其回调方法
      AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1778) // 在这个方法中初始化bean
      AbstractAutowireCapableBeanFactory.populateBean // 为bean的属性赋值,如注入依赖
      AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:602) // 在这个方法中执行创建bean的逻辑
      AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) // 创建bean
      AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
      AbstractBeanFactory$$Lambda$301.692743054.getObject(Unknown Source:-1)
      DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) // 从 Map<String, Object> singletonObjects = new ConcurrentHashMap(256);缓存中获取单实例bean
      AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) // 在这个方法中执行获取bean的逻辑
      AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) // 先尝试获取bean
      DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944) // 实例化所有剩余的(非延迟初始化)单例bean
      AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) // 初始化剩下的所有单实例对象
      AbstractApplicationContext.refresh(AbstractApplicationContext.java:567) // 向BeanFactory中注册所有的bean的后置处理器,用来后续拦截bean的创建过程
      AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) // refresh()方法,刷新容器
      AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:93) // AnnotationConfigApplicationContext构造器中调用 refresh()方法
      AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationContextConfig.class);    //创建IOC容器

 

 

 

 

五、BeanPostProcessor工作原理

   BeanPostProcessor原理

  populateBean(beanName, mbd, instanceWrapper);  给bean进行属性赋值
  initializeBean
  {
    applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    invokeInitMethods(beanName, wrappedBean, mbd);  执行自定义初始化
    applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

      遍历得到容器中所有的BeanPostProcessor;挨个执行postProcessBeforeInitialization(),一但返回null,跳出for循环,不会执行后面的BeanPostProcessor.postProcessorsBeforeInitialization

  }

 

 

 

  Spring底层对BeanPostProcessor的使用:

    1、其实现类ApplicationContextAwareProcessor可对实现了ApplicationContextAware接口及一些其他xxxAware接口的bean 注入容器ApplicationContext依赖对象及其他 xxx 依赖对象

      postProcessBeforeInitialization方法中执行依赖的注入,代码如下:

    private void invokeAwareInterfaces(Object bean) {
        if (bean instanceof EnvironmentAware) {
            ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
        }
        if (bean instanceof EmbeddedValueResolverAware) {
            ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
        }
        if (bean instanceof ResourceLoaderAware) {
            ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
        }
        if (bean instanceof ApplicationEventPublisherAware) {
            ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
        }
        if (bean instanceof MessageSourceAware) {
            ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
        }
        if (bean instanceof ApplicationStartupAware) {
            ((ApplicationStartupAware) bean).setApplicationStartup(this.applicationContext.getApplicationStartup());
        }
        if (bean instanceof ApplicationContextAware) {
            ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
        }
    }

 

    2、其实现类InitDestroyAnnotationBeanPostProcessor,对bean中标注了@PostContruct和@PreDestory注解的方法进行调用执行

    3、其实现类AutowiredAnnotationBeanPostProcessor,在对象创建完成以后,对所有标注了@Autowired注解的属性进行注入值

 

 

六:属性赋值

  1、使用@Value赋值

    此注解值的注入发生在AutowiredAnnotationBeanPostProcessor类中。

    使用方式:

    ①:可以直接写基本数值,如@Value("123")

    ②:可以写SPEL表达式#{}

    ③:可以写${},取出在配置文件中配置的(@PropertySource指定外部配置文件),容器启动加载到 环境变量Environment中的值

 

  2、自动装配

    创建容器中对象协作关系的行为叫做装配,是DI的核心。

    自动装配:即Spring利用依赖注入DI,完成对IOC容器中各个组件的依赖关系赋值

    1、@AutoWired,自动注入(可标注在setter方法、参数、构造器上)

      1)默认按照类型byType(applicationContext.getBean(xxx.class))去容器中找对应的组件,然后注入;
      2)如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找
      3)@Qualifier("xxx"):指定需要装配的组件的名字
      4)自动装配默认一定要将属性赋值好,没有就会报错,可以使用@AutoWired(required=false),允许不注入
      5)@Primary:用在依赖的类上,让Spring进行自动装配的时候,默认首选装配它 

    2、@Resource
      和@AutoWired一样实现自动装配功能,默认是按照属性名称ByName进行装配的,按名称没有找到则再按类型进行装配,如果指定了name或者type则按照名称和类型进行装配,没有找到则报错

    3、Inject
      需要导入javax.inject的包,和Autowired的功能一样。没有required=false的功能

 

    @Autowired:Spring定义的; @Resource、@Inject都是java规范

    以上注解的自动装配是由 AutowiredAnnotationBeanPostProcessor 解析完成的。

 

    4、自定义组件想要使用Spring容器底层的一些组件(ApplicationContext,BeanFactory,xxx);
      自定义组件实现xxxAware;在创建对象的时候,会调用接口规定的方法注入相关组件;Aware;
      把Spring底层一些组件注入到自定义的Bean中;
      xxxAware:功能使用xxxProcessor,是通过后置处理器来实现的。如:ApplicationContextAware==》ApplicationContextAwareProcessor;

 


  3、高级装配

    @Profile(value = "env"):指定组件在哪个环境的情况下才能被注册到容器中。

      1、加了环境标识的bean,只有在这个环境被激活的时候才能注册到容器中,默认激活环境是default

      2、若标注在配置类上,则只有在执行的环境激活的时候,整个配置类里面的所有配置才生效

      3、没有标注环境标识@Profile注解的bean在任何环境下都会注册的

 

    如何激活Profile环境:

    1、使用命令行动态参数:在虚拟机参数位置加载 -Dspring.profiles.active=test

    2、代码的方式激活某个环境变量,需要在启动Spring容器的时候使用无参构造不传配置文件的参数

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        // 设置需要激活的环境
        context.getEnvironment().setActiveProfiles("pre");
        // 注册主配置类,多个配置类逗号隔开
        context.register(ApplicationContextConfig.class);
        // 启动刷新容器
        context.refresh();

 

 

疑问?

  AutowiredAnnotationBeanPostProcessor 注入依赖的时机?

  populateBean 给属性赋值,也能注入依赖,那么和AutowiredAnnotationBeanPostProcessor 注入依赖什么关系,先后顺序?

 

 

 

END.

     

posted @ 2019-06-01 00:14  杨岂  阅读(1558)  评论(0编辑  收藏  举报