• Spring Bean的生命周期、Java配置BeanFactoryPostProcessor失效与解决


    BeanFactory 与 ApplicationContext 的区别

    1. 到底什么是 BeanFactory

      • 它是 ApplicationContext 的父接口

      • 它才是 Spring 的核心容器, 主要的 ApplicationContext 实现都【组合】了它的功能,【组合】是指 ApplicationContext 的一个重要成员变量就是 BeanFactory

    1. BeanFactory 能干点啥

      • 表面上只有 getBean

      • 实际上控制反转、基本的依赖注入、直至 Bean 的生命周期的各种功能,都由它的实现类提供

      • 例子中通过反射查看了它的成员变量 singletonObjects,内部包含了所有的单例 bean

    1. ApplicationContext 比 BeanFactory 多点啥

      • ApplicationContext 组合并扩展了 BeanFactory 的功能

      • 国际化、通配符方式获取一组 Resource 资源、整合 Environment 环境、事件发布与监听

      • 事件解耦(org.springframework.context.ApplicationEventPublisher#publishEvent(java.lang.Object) 、org.springframework.context.event.EventListener)

    2) 容器实现

    • DefaultListableBeanFactory,是 BeanFactory 最重要的实现,像控制反转依赖注入功能,都是它来实现

    • ClassPathXmlApplicationContext,从类路径查找 XML 配置文件,创建容器(旧)

    • FileSystemXmlApplicationContext,从磁盘路径查找 XML 配置文件,创建容器(旧)

    • XmlWebApplicationContext,传统 SSM 整合时,基于 XML 配置文件的容器(旧)

    • AnnotationConfigWebApplicationContext,传统 SSM 整合时,基于 java 配置类的容器(旧)

    • AnnotationConfigApplicationContext,Spring boot 中非 web 环境容器(新)

    • AnnotationConfigServletWebServerApplicationContext,Spring boot 中 servlet web 环境容器(新)

    • AnnotationConfigReactiveWebServerApplicationContext,Spring boot 中 reactive web 环境容器(新)

    另外要注意的是,后面这些带有 ApplicationContext 的类都是 ApplicationContext 接口的实现,但它们是组合DefaultListableBeanFactory 的功能,并非继承而来。

    • beanFactory 可以通过 registerBeanDefinition 注册一个 bean definition 对象

      • 我们平时使用的配置类、xml、组件扫描等方式都是生成 bean definition 对象注册到 beanFactory 当中

      • bean definition 描述了这个 bean 的创建蓝图:scope 是什么、用构造还是工厂创建、初始化销毁方法是什么,等等

    1. DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
    2. // bean 的定义(class, scope, 初始化, 销毁)
    3. // My: 使用建造者模式 生成bean的定义( bean 类名) 设置作用域 单例。 建造
    4. AbstractBeanDefinition beanDefinition =
    5. BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();
    6. // My:在beanFactory添加(注册Bean定义)一个Bean
    7. beanFactory.registerBeanDefinition("config", beanDefinition);
    • beanFactory 需要手动调用 beanFactory 后处理器对它做增强

      • 例如通过解析 @Bean、@ComponentScan 等注解,来补充一些 bean definition

    • beanFactory 需要手动添加 bean 后处理器,以便对后续 bean 的创建过程提供增强

      • 例如 @Autowired,@Resource 等注解的解析都是 bean 后处理器完成的

      • bean 后处理的添加顺序会对解析结果有影响,见视频中同时加 @Autowired,@Resource 的例子

    • beanFactory 需要手动调用方法来初始化单例

    • beanFactory 需要额外设置才能解析 ${} 与 #{}

    3) Bean 的生命周期

    BeanFactory 文档注释未提及 InstantiationAwareBeanPostProcessor

    InstantiationAwareBeanPostProcessor -> 
    BeanPostProcessor -> DestructionAwareBeanPostProcessor

    创建前后的增强

    • postProcessBeforeInstantiation

      • 这里返回的对象若不为 null 会替换掉原本的 bean,并且仅会走 postProcessAfterInitialization 流程

    • postProcessAfterInstantiation

    依赖注入前的增强

    • postProcessProperties

      • 如 @Autowired、@Value、@Resource

    初始化前后的增强

    • postProcessBeforeInitialization

      • 这里返回的对象会替换掉原本的 bean

      • 如 @PostConstruct、@ConfigurationProperties

    • postProcessAfterInitialization

      • 这里返回的对象会替换掉原本的 bean

      • 如代理增强

    销毁之前的增强

    • postProcessBeforeDestruction

      • 如 @PreDestroy

     

    演示2 - 模板方法设计模式

     Bean的生命周期 第14 步可添加多个 BeanPostProcessor 在这里拓展一种模板方法设计模式

    1. import java.util.function.BiFunction;
    2. /**
    3. * 自定义的函数对象 参照了 org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String)
    4. * @author Jay
    5. */
    6. public class MyBeanPostProcessor {
    7. /**
    8. * Bean 后处理器
    9. */
    10. private BiFunction function;
    11. /**
    12. * T,参数一
    13. */
    14. private Object bean;
    15. /**
    16. * U, 参数二
    17. */
    18. private String beanName;
    19. /**
    20. * R, BiFunction 的返回值
    21. */
    22. private Object returnValue;
    23. /**
    24. * 需要全部的参数才能实例化
    25. * @param bean
    26. * @param beanName
    27. * @param function
    28. */
    29. public MyBeanPostProcessor(Object bean, String beanName, BiFunction function) {
    30. this.bean = bean;
    31. this.beanName = beanName;
    32. this.function = function;
    33. }
    34. public BiFunction getFunction() {
    35. return function;
    36. }
    37. public void setFunction(BiFunction function) {
    38. this.function = function;
    39. }
    40. public Object getBean() {
    41. return bean;
    42. }
    43. public void setBean(Object bean) {
    44. this.bean = bean;
    45. }
    1. import java.util.ArrayList;
    2. import java.util.List;
    3. public abstract class Game {
    4. private List processors = new ArrayList<>();
    5. /**
    6. * 初始化游戏
    7. */
    8. abstract void initialize();
    9. /**
    10. * 开始游戏
    11. */
    12. abstract void startPlay();
    13. /**
    14. * 结束游戏
    15. */
    16. abstract void endPlay();
    17. public void addFunction(MyBeanPostProcessor function) {
    18. processors.add(function);
    19. }
    20. /**
    21. * 模板方法 不可重写
    22. */
    23. public final void play() {
    24. initialize();
    25. startPlay();
    26. // 依次执行 MyBeanPostProcessor 的 getReturnValue
    27. for (MyBeanPostProcessor processor : processors) {
    28. // processor.getFunction().apply(processor.getBean(), processor.getBeanName());
    29. processor.getReturnValue();
    30. }
    31. endPlay();
    32. }
    33. }
    1. public class FootBall extends Game{
    2. @Override
    3. void initialize() {
    4. System.out.println("FootBall Game initializing...");
    5. }
    6. @Override
    7. void startPlay() {
    8. System.out.println("FootBall Game startPlay");
    9. }
    10. @Override
    11. void endPlay() {
    12. System.out.println("FootBall Game is end");
    13. }
    14. }
    1. public class Cricket extends Game{
    2. @Override
    3. public final void initialize() {
    4. System.out.println("Cricket Game initialize");
    5. }
    6. @Override
    7. public final void startPlay() {
    8. System.out.println("Cricket Game startPlay");
    9. }
    10. @Override
    11. public final void endPlay() {
    12. System.out.println("Cricket Game endPlay");
    13. }
    14. }
    1. /**
    2. * @author Jay
    3. */
    4. public class TemplatePatternDemo {
    5. public static void main(String[] args) {
    6. Game footBall = new FootBall();
    7. // 添加 BeanPostProcessor
    8. footBall.addFunction(
    9. new MyBeanPostProcessor("1", "1", (bean, beanName) -> {
    10. System.out.println("解析 @Bean");
    11. return bean;
    12. })
    13. );
    14. footBall.addFunction(
    15. new MyBeanPostProcessor("1", "1", (bean, beanName) -> {
    16. System.out.println("解析 @Resource");
    17. return bean;
    18. })
    19. );
    20. footBall.addFunction(
    21. new MyBeanPostProcessor("1", "1", (bean, beanName) -> {
    22. System.out.println("解析 @Autowired");
    23. return bean;
    24. })
    25. );
    26. footBall.play();
    27. Game cricket = new Cricket();
    28. cricket.play();
    29. }
    30. }

    bean(后处理器)排序

    收获💡

    1. 实现了 PriorityOrdered 接口的优先级最高

    2. 实现了 Ordered 接口与加了 @Order 注解的平级, 按数字升序

    3. 其它的排在最后

    PostProcessorRegistrationDelegate[ AbstractApplicationContext的后处理器处理的委托]

     注册与调用 BeanFactoryPostProcessor bean

     Bean后处理器的注册与使用

    注册 :org.springframework.beans.factory.config.ConfigurableBeanFactory#addBeanPostProcessor

     调用:org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(java.util.Collection, org.springframework.beans.factory.config.ConfigurableListableBeanFactory)

    1. import org.slf4j.Logger;
    2. import org.slf4j.LoggerFactory;
    3. import org.springframework.beans.factory.annotation.Autowired;
    4. import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
    5. import org.springframework.beans.factory.config.BeanPostProcessor;
    6. import org.springframework.beans.factory.support.AbstractBeanDefinition;
    7. import org.springframework.beans.factory.support.BeanDefinitionBuilder;
    8. import org.springframework.beans.factory.support.DefaultListableBeanFactory;
    9. import org.springframework.context.annotation.AnnotationConfigUtils;
    10. import org.springframework.context.annotation.Bean;
    11. import org.springframework.core.Ordered;
    12. import javax.annotation.Resource;
    13. public class TestBeanFactory {
    14. public static void main(String[] args) {
    15. DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
    16. // bean 的定义(class, scope, 初始化, 销毁)
    17. // My: 使用建造者模式 生成bean的定义( bean 类名) 设置作用域 单例。 建造
    18. AbstractBeanDefinition beanDefinition =
    19. BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();
    20. // My:在beanFactory添加(注册Bean定义)一个Bean
    21. beanFactory.registerBeanDefinition("config", beanDefinition);
    22. // 给 BeanFactory 添加一些常用的后处理器
    23. // My:在给定的注册表中注册所有相关的注释后处理器
    24. AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
    25. // BeanFactory 后处理器主要功能,补充了一些 bean 定义
    26. // 通过Bean的类型获取(后处理器)PostProcessor
    27. beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().forEach(beanFactoryPostProcessor -> {
    28. // 执行BeanFactory后处理器
    29. beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
    30. });
    31. // Bean 后处理器, 针对 bean 的生命周期的各个阶段提供扩展, 例如 @Autowired @Resource ...
    32. // 先加入的 Bean后处理器的优先级更高一点。 所以 @Autowired 高于 @Resource 但是顺序也是可以控制的
    33. beanFactory.getBeansOfType(BeanPostProcessor.class).values().stream()
    34. .sorted(beanFactory.getDependencyComparator())
    35. .forEach(beanPostProcessor -> {
    36. System.out.println(">>>>" + beanPostProcessor);
    37. beanFactory.addBeanPostProcessor(beanPostProcessor);
    38. });
    39. for (String name : beanFactory.getBeanDefinitionNames()) {
    40. System.out.println(name);
    41. }
    42. }
    43. interface Inter {
    44. }
    45. static class Bean3 implements Inter {
    46. }
    47. static class Bean4 implements Inter {
    48. }
    49. static class Bean1 {
    50. private static final Logger log = LoggerFactory.getLogger(Bean1.class);
    51. public Bean1() {
    52. log.debug("构造 Bean1()");
    53. }
    54. @Autowired
    55. private Bean2 bean2;
    56. public Bean2 getBean2() {
    57. return bean2;
    58. }
    59. @Autowired
    60. @Resource(name = "bean4") // resource 比Autowired 找的就高级一些了
    61. // 当我使用接口时候 使用的是成员变量的名字 inter去找 就可能找不到了
    62. // 两个同时存在的话 因为BeanPostProcessor相关的后处理器的默认顺序AutowiredAnnotation比CommonAnnotation 优先级高所以 AutoWired高
    63. // 可通过 sorted 的 dependencyComparator控制顺序
    64. private Inter bean3;
    65. public Inter getInter() {
    66. return bean3;
    67. }
    68. }
    69. static class Bean2 {
    70. private static final Logger log = LoggerFactory.getLogger(Bean2.class);
    71. public Bean2() {
    72. log.debug("构造 Bean2()");
    73. }
    74. }
    75. }

    4) Bean 后处理器

            自定义修改新bean实例

    演示1 - 后处理器作用

    代码参考

    com.itheima.a04

    收获💡

    1. @Autowired 等注解的解析属于 bean 生命周期阶段(依赖注入, 初始化)的扩展功能,这些扩展功能由 bean 后处理器来完成

    2. 每个后处理器各自增强什么功能

      • AutowiredAnnotationBeanPostProcessor 解析 @Autowired 与 @Value

      • CommonAnnotationBeanPostProcessor 解析 @Resource、@PostConstruct、@PreDestroy

      • ConfigurationPropertiesBindingPostProcessor 解析 @ConfigurationProperties

    3. 另外 ContextAnnotationAutowireCandidateResolver 负责获取 @Value 的值,解析 @Qualifier、泛型、@Lazy 等

     

    演示2 - @Autowired bean 后处理器运行分析

    代码参考

    com.itheima.a04.DigInAutowired

    1. import org.springframework.beans.PropertyValues;
    2. import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
    3. import org.springframework.beans.factory.annotation.InjectionMetadata;
    4. import org.springframework.beans.factory.config.DependencyDescriptor;
    5. import org.springframework.beans.factory.support.DefaultListableBeanFactory;
    6. import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver;
    7. import org.springframework.core.MethodParameter;
    8. import org.springframework.core.env.StandardEnvironment;
    9. import java.lang.reflect.Field;
    10. import java.lang.reflect.Method;
    11. // AutowiredAnnotationBeanPostProcessor 运行分析
    12. public class DigInAutowired {
    13. public static void main(String[] args) throws Throwable {
    14. DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
    15. beanFactory.registerSingleton("bean2", new Bean2()); // 创建过程,依赖注入,初始化
    16. beanFactory.registerSingleton("bean3", new Bean3());
    17. beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); // @Value
    18. // 添加字符串解析器
    19. beanFactory.addEmbeddedValueResolver(new StandardEnvironment()::resolvePlaceholders); // ${} 的解析器
    20. // 1. 查找哪些属性、方法加了 @Autowired, 这称之为 InjectionMetadata
    21. AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
    22. processor.setBeanFactory(beanFactory);
    23. Bean1 bean1 = new Bean1();
    24. System.out.println(bean1);
    25. processor.postProcessProperties(null, bean1, "bean1"); // 执行依赖注入 @Autowired @Value
    26. System.out.println(bean1);
    27. // processor.postProcessProperties 所做的工作: 1\查找注解 @Autowired @Value findAutowiringMetadata() 2\执行注入 metadata.inject()
    28. // 解析{} 需要使用EmbeddedValueResolver
    29. Method findAutowiringMetadata = AutowiredAnnotationBeanPostProcessor.class
    30. .getDeclaredMethod("findAutowiringMetadata", String.class, Class.class, PropertyValues.class);
    31. findAutowiringMetadata.setAccessible(true);
    32. InjectionMetadata metadata = (InjectionMetadata) findAutowiringMetadata
    33. .invoke(processor, "bean1", Bean1.class, null);// 获取 Bean1 上加了 @Value @Autowired 的成员变量,方法参数信息
    34. System.out.println(metadata);
    35. // 2. 调用 InjectionMetadata 来进行依赖注入, 注入时按类型查找值
    36. metadata.inject(bean1, "bean1", null);
    37. System.out.println(bean1);
    38. // 3. 如何按类型查找值
    39. Field bean3 = Bean1.class.getDeclaredField("bean3");
    40. DependencyDescriptor dd1 = new DependencyDescriptor(bean3, false);
    41. // 根据一个依述赖描(字段)获取一个对象
    42. Object o = beanFactory.doResolveDependency(dd1, null, null, null);
    43. System.out.println(o);
    44. Method setBean2 = Bean1.class.getDeclaredMethod("setBean2", Bean2.class);
    45. DependencyDescriptor dd2 =
    46. new DependencyDescriptor(new MethodParameter(setBean2, 0), true);
    47. Object o1 = beanFactory.doResolveDependency(dd2, null, null, null);
    48. System.out.println(o1);
    49. Method setHome = Bean1.class.getDeclaredMethod("setHome", String.class);
    50. DependencyDescriptor dd3 = new DependencyDescriptor(new MethodParameter(setHome, 0), true);
    51. Object o2 = beanFactory.doResolveDependency(dd3, null, null, null);
    52. System.out.println(o2);
    53. }
    54. }

    收获💡

    1. AutowiredAnnotationBeanPostProcessor.findAutowiringMetadata 用来获取某个 bean 上加了 @Value @Autowired 的成员变量,方法参数的信息,表示为 InjectionMetadata

    2. InjectionMetadata 可以完成依赖注入

    3. InjectionMetadata 内部根据成员变量,方法参数封装为 DependencyDescriptor 类型

    4. 有了 DependencyDescriptor,就可以利用 beanFactory.doResolveDependency 方法进行基于类型的查找

     

    5) BeanFactory 后处理器

    它允许自定义修改应用程序上下文的bean定义,但不能与bean实例交互。

    使用方法:实现了BeanFactoryPostProcessor 接口(子接口也可以 BeanDefinitionRegistryPostProcessor) 

    定义顺序: 接口 Ordered 与 接口 PriorityOrdered

    特别考虑返回 Spring BeanFactoryPostProcessor ( BFPP ) 类型的@Bean方法

    • ConfigurationClassPostProcessor 可以解析:@ComponentScan、@Bean、@Import、@ImportResource

    • MapperScannerConfigurer 可以解析:Mapper 接口(@MapperScan)

    演示2 - 模拟解析 @ComponentScan

    BeanFactoryPostProcessor 解析@Configuration 类的注册信息,利用 ConfigurationClassParser 进行解析并添加Bean的定义

    1. public class ComponentScanPostProcessor implements BeanDefinitionRegistryPostProcessor {
    2. @Override // context.refresh
    3. public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
    4. }
    5. // 标准初始化之后修改应用程序上下文的内部 bean 定义注册表(加更多的 bean 定义)
    6. @Override
    7. public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanFactory) throws BeansException {
    8. try {
    9. // AnnotationUtils 扫描 Config.class 类上的 @ComponentScan的 basePackages
    10. ComponentScan componentScan = AnnotationUtils.findAnnotation(Config.class, ComponentScan.class);
    11. if (componentScan != null) {
    12. for (String p : componentScan.basePackages()) {
    13. System.out.println(p);
    14. // com.itheima.a05.component -> classpath*:com/itheima/a05/component/**/*.class
    15. String path = "classpath*:" + p.replace(".", "/") + "/**/*.class";
    16. System.out.println(path);
    17. // MetadataReader 不走反射,效率很高 使用工厂方法创建,
    18. CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
    19. Resource[] resources = new PathMatchingResourcePatternResolver().getResources(path);
    20. AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();
    21. for (Resource resource : resources) {
    22. // System.out.println(resource);
    23. MetadataReader reader = factory.getMetadataReader(resource);
    24. // System.out.println("类名:" + reader.getClassMetadata().getClassName());
    25. AnnotationMetadata annotationMetadata = reader.getAnnotationMetadata();
    26. // System.out.println("是否加了 @Component:" + annotationMetadata.hasAnnotation(Component.class.getName()));
    27. // System.out.println("是否加了 @Component 派生:" + annotationMetadata.hasMetaAnnotation(Component.class.getName()));
    28. if (annotationMetadata.hasAnnotation(Component.class.getName())
    29. || annotationMetadata.hasMetaAnnotation(Component.class.getName())) {
    30. AbstractBeanDefinition bd = BeanDefinitionBuilder
    31. .genericBeanDefinition(reader.getClassMetadata().getClassName())
    32. .getBeanDefinition();
    33. String name = generator.generateBeanName(bd, beanFactory);
    34. beanFactory.registerBeanDefinition(name, bd);
    35. }
    36. }
    37. }
    38. }
    39. } catch (IOException e) {
    40. e.printStackTrace();
    41. }
    42. }
    43. }
    1. // 表示一个类声明了一个或多个@Bean方法
    2. @Configuration
    3. // Configuration组件扫描指令以与@Configuration 类一起使用。
    4. // 提供与 Spring XML 的元素并行的支持
    5. @ComponentScan("component")
    6. public class Config {
    7. }
    1. package component;
    2. @Component
    3. public class Bean2 {
    4. private static final Logger log = LoggerFactory.getLogger(Bean2.class);
    5. public Bean2() {
    6. log.debug("我被 Spring 管理啦");
    7. }
    8. }
    9. package component;
    10. import org.slf4j.Logger;
    11. import org.slf4j.LoggerFactory;
    12. import org.springframework.stereotype.Controller;
    13. @Controller
    14. public class Bean3 {
    15. private static final Logger log = LoggerFactory.getLogger(Bean3.class);
    16. public Bean3() {
    17. log.debug("我被 Spring 管理啦");
    18. }
    19. }
    1. /*
    2. BeanFactory 后处理器的作用
    3. */
    4. public class A05 {
    5. private static final Logger log = LoggerFactory.getLogger(A05.class);
    6. public static void main(String[] args) throws IOException {
    7. // ⬇️GenericApplicationContext 是一个【干净】的容器
    8. GenericApplicationContext context = new GenericApplicationContext();
    9. // 使用此方式注册Bean @Configuration注解并未生效。 而是手动指定的
    10. context.registerBean("config", Config.class);
    11. // Config类需要先被加载进来
    12. // ConfigurationClass PostProcessor 会扫描具有@Configuration注解的类
    13. // 间接注册了 ComponentScanPostProcessor AtBeanPostProcessor
    14. // context.registerBean(ConfigurationClassPostProcessor.class); // @ComponentScan @Bean @Import @ImportResource
    15. // context.registerBean(MapperScannerConfigurer.class, bd -> { // @MapperScanner
    16. // bd.getPropertyValues().add("basePackage", "com.itheima.a05.mapper");
    17. // });
    18. //
    19. context.registerBean(ComponentScanPostProcessor.class); // 解析 @ComponentScan
    20. // context.registerBean(AtBeanPostProcessor.class); // 解析 @Bean
    21. // context.registerBean(MapperPostProcessor.class); // 解析 Mapper 接口
    22. // ⬇️初始化容器
    23. context.refresh();
    24. for (String name : context.getBeanDefinitionNames()) {
    25. System.out.println(name);
    26. }
    27. // ⬇️销毁容器
    28. context.close();
    29. /*
    30. 学到了什么
    31. a. @ComponentScan, @Bean, @Mapper 等注解的解析属于核心容器(即 BeanFactory)的扩展功能
    32. b. 这些扩展功能由不同的 BeanFactory 后处理器来完成, 其实主要就是补充了一些 bean 定义
    33. */
    34. }
    35. }

    6) Aware 接口

    1. Aware 接口提供了一种【内置】 的注入手段,例如

      • BeanNameAware 注入 bean 的名字

      • BeanFactoryAware 注入 BeanFactory 容器

      • ApplicationContextAware 注入 ApplicationContext 容器

      • EmbeddedValueResolverAware 注入 ${} 解析器

    2. InitializingBean 接口提供了一种【内置】的初始化手段

    3. 对比

      • 内置的注入和初始化不受扩展功能的影响,总会被执行

      • 而扩展功能受某些情况影响可能会失效

      • 因此 Spring 框架内部的类常用内置注入和初始化

    配置类 @Autowired 失效

     原因分析:

    Java 配置类包含 BeanFactoryPostProcessor 的情况,因此要创建其中的BeanFactory-PostProcessor 必须提前创建 Java 配置类,而此时的 BeanPostProcessor 还未准备好,导致 @Autowired 等注解失效

     正常情况应为:

     解决方法为

            用静态工厂方法代替实例工厂方法,避免工厂对象提前被创建(不会针对作用域和AOP语义进行增强)

            使用Aware接口(ApplicationContextAware实现依赖注入、BeanNameAware 自定义 Bean 的名字)实现 InitializingBean 接口(对初始化进行增强)

    1. import org.slf4j.Logger;
    2. import org.slf4j.LoggerFactory;
    3. import org.springframework.beans.BeansException;
    4. import org.springframework.beans.factory.BeanNameAware;
    5. import org.springframework.beans.factory.InitializingBean;
    6. import org.springframework.beans.factory.annotation.Autowired;
    7. import org.springframework.context.ApplicationContext;
    8. import org.springframework.context.ApplicationContextAware;
    9. import javax.annotation.PostConstruct;
    10. /**
    11. * 可以继续使用 @Autowired @PostConstruct 等注解了
    12. * @author Jay
    13. */
    14. public class MyBean implements BeanNameAware, ApplicationContextAware, InitializingBean {
    15. private static final Logger log = LoggerFactory.getLogger(MyBean.class);
    16. @Override
    17. public void setBeanName(String name) {
    18. log.debug("当前bean " + this + " 名字叫:" + name);
    19. }
    20. @Override
    21. public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    22. log.debug("当前bean " + this + " 容器是:" + applicationContext);
    23. }
    24. @Override
    25. public void afterPropertiesSet() throws Exception {
    26. log.debug("当前bean " + this + " 初始化");
    27. }
    28. @Autowired
    29. public void aaa(ApplicationContext applicationContext) {
    30. log.debug("当前bean " + this + " 使用@Autowired 容器是:" + applicationContext);
    31. }
    32. @PostConstruct
    33. public void init() {
    34. log.debug("当前bean " + this + " 使用@PostConstruct 初始化");
    35. }
    36. }

    文章来源:

    【黑马程序员Spring视频教程,深度讲解spring5底层原理】icon-default.png?t=M85Bhttps://www.bilibili.com/video/BV1P44y1N7QG?share_source=copy_web&vd_source=35de0ae939ec5cd0c4e3d33b6b5d3192

  • 相关阅读:
    解决vscode保存时,代码自动格式化问题
    业内专业人士揭秘:双11即将来临,挑选SSD硬盘避坑指南
    计算机毕业设计JAVA百姓点评网的设计与实现mybatis+源码+调试部署+系统+数据库+lw
    coreldraw2018零售版最新下载步骤
    MySQL数据库管理及数据库基本操作
    【openGauss】让gsql和sqlplus输出包含有SQL及数据的完全一致的文本文件
    C#图解教程总结(第二章)
    Java学习笔记 --- HashMap
    博客 - - Hexo + fluid + Github 搭建教程(github.io)
    融云 CDN 播放器 2.0 版本正式上线
  • 原文地址:https://blog.csdn.net/qq_34922830/article/details/127079783