Spring Aware接口

第一次遇见这个接口,是在Bean的初始化过程中。初始化的第一步就是 invokeAwareMethods ,执行Aware子接口的相关set方法。

网上查资料,大多是术语比如:感知自己的属性。不明白的是,有什么实际应用

先看抛出一个常见需求,我需要在一个类A里获取一个Bean,但是类A不是一个Bean(不由Spring管理,没办法Autowired来注入其它Bean)。

那么我们首先要获取到上下文的实例,然后获取任何Bean就不成问题了。

这个时候我们就可以利用Aware接口的特性来帮助我们获取到ApplicationContext实例了。

实现Aware接口

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

/**
 * Aware接口的实际应用
 */
public class ApplicationContextUtils implements ApplicationContextAware,BeanNameAware {

    private static ApplicationContext applicationContext;
    private static String name;

    /**
     * 设置当前应用程序上下文
     * @param applicationContext
     * @throws BeansException
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ApplicationContextUtils.applicationContext = applicationContext;
    }

    public static <T> T getBean(String name, Class<T> clazz){
        return applicationContext.getBean(name, clazz);
    }

    /**
     * 设置当前Bean的名称
     * @param name
     */
    @Override
    public void setBeanName(String name) {
        ApplicationContextUtils.name = name;
    }

    public static String getName(){
        return name;
    }
}

这里我实现了两个接口,分别“感知”自己的上下文和bean名称

一个简单实体类

import lombok.Getter;

@Getter
public class User {
    private String name = "AAA";
}

配置类

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class SimpleConfig {

    /**
     * 配置工具类,默认以方法名称为bean名称(实现Aware接口的类要交给Spring管理)
     * @return
     */
    @Bean
    public ApplicationContextUtils applicationContextUtils(){
        return new ApplicationContextUtils();
    }

    @Bean("user")
    public User getUser(){
        return new User();
    }
}

启动

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {
    public static void main(String[] args) throws Exception {
        // 启动容器
        ApplicationContext context = new AnnotationConfigApplicationContext(SimpleConfig.class);
        // 使用工具类来“感知”应用程序上下文,进而手动getBean
        User user = ApplicationContextUtils.getBean("user", User.class);
        System.out.println(user.getName());
        // 感知bean名称
        System.out.println(ApplicationContextUtils.getName());
    }
}

输出

总结

这么一来,Aware接口的作用就清晰明了了。

1. Aware接口是个标记接口,标记这一类接口是用来“感知”自己属性的。

2. Aware的众多子接口则是实现了:我具体要“感知”什么属性

3. Aware子接口的实现类则是:我要拿到你能“感知”到的属性,为我所用。

另附Aware子接口

对于初始化的时候涉及的Aware接口:

初始化方法全路径:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)

invokeAwareMethods方法:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeAwareMethods

这里涉及三个Aware子接口:BeanNameAware、BeanClassLoaderAware、BeanFactoryAware

实际上另外一些接口

在容器启动,刷新方法第三步:org.springframework.context.support.AbstractApplicationContext#prepareBeanFactory

其中有一行:

beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

后面这个类里有个 postProcessBeforeInitialization 方法,在每个Bean初始化之前调用。

里面有个 invokeAwareInterfaces 方法

这里涉及:EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware

原文地址:https://www.cnblogs.com/LUA123/p/12362028.html