第6讲 - Aware和InitializingBean接口

发布于:2022-10-29 ⋅ 阅读:(402) ⋅ 点赞:(0)

Aware和InitializingBean接口的作用

  • BeanNameAware:注入bean的名字
  • BeanFactoryAware:注入BeanFactory容器
  • ApplicationContextAware:注入ApplicationContext容器
  • EmbeddedValueResolverAware:解析 ${}

  • InitializingBean:初始化bean调用

自定义Bean对象实现BeanNameAware、ApplicationContextAware、InitializingBean接口。 

public class Bean01 implements BeanNameAware, ApplicationContextAware, InitializingBean {
    @Override
    public void setBeanName(String name) {
        System.out.println("Bean01 name is " + name);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("当前容器是: " + applicationContext);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("当前bean初始化: " + this);
    }
}
public class A06Application {
    public static void main(String[] args) {
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("myBean01", Bean01.class);
        context.refresh();
        context.close();
    }
}

Bean01 name is myBean01
当前容器是: org.springframework.context.support.GenericApplicationContext@19e1023e, started on Sat Oct 29 14:30:40 CST 2022
当前bean初始化: com.shuttle.spring5.Bean01@148080bb

为什么有了@Autowired等注解还需要Aware接口呢?

简单的说:

  • @Autowired的解析需要用到Bean后处理器,属于扩展功能
  • Aware接口属于内置功能,不需要添加任何扩展Spring就能识别

在某些情况下,扩展功能会失效,但内置功能不会。

@Configuration
public class MyConfig1 {

    @Autowired
    public void setApplicationContext(ApplicationContext applicationContext) {
        System.out.println("@Autowired 注入ApplicationContext");
    }

    @PostConstruct
    public void init() {
        System.out.println("初始化...");
    }

}

    public static void main(String[] args) {
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("myConfig1", MyConfig1.class);
        context.registerBean(AutowiredAnnotationBeanPostProcessor.class);
        context.registerBean(CommonAnnotationBeanPostProcessor.class);
        context.registerBean(ConfigurationClassPostProcessor.class);
        context.refresh();
        context.close();
    }

运行上述程序结果如下:

@Autowired 注入ApplicationContext
初始化...

看起来还比较正常,一起来看看什么情况下注解会失效吧~

在配置类中添加如下代码:

    @Bean
    public BeanFactoryPostProcessor processor() {
        return beanFactory -> {
            System.out.println("execute processor...");
        };
    }

程序运行没有发现和@Autowired、@PostConstruct注解解析有关的信息。

为什么会出现上述情况呢?一起来看看【截取自满老师的课件】

简单来说,就是在配置类中注入BeanFactoryPostProcessor对象导致需要提前创建和初始化配置类,越过了注册BeanPostProcessor后处理器,进而导致@Autowired等注解解析不生效。 

 

解决方案:使用内置接口

@Configuration
public class MyConfig2 implements ApplicationContextAware, InitializingBean {

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("初始化...");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("当前容器是: " + applicationContext);
    }

    @Bean
    public BeanFactoryPostProcessor processor() {
        return beanFactory -> {
            System.out.println("execute processor...");
        };
    }
}

 注入MyConfig2对象后程序运行结果如下:

当前容器是: org.springframework.context.support.GenericApplicationContext@19e1023e, started on Sat Oct 29 14:53:44 CST 2022
初始化...

execute processor...