Spring接口

FactoryBean接口

Spring中有两种类型的Bean:一种是普通的JavaBean;另一种就是工厂Bean(FactoryBean),这两种Bean都受Spring的IoC容器管理。

FactoryBean 是一个特殊的bean,要想得到FactoryBean本身,必须通过&FactoryBeanName,可以在BeanFactory中通过getBean(&FactoryBeanName)来得到 FactoryBean。

一般来说我们自己写的Bean在只继承自己的接口时创建Bean的过程是交给IOC容器来实现的。但是某些特殊情况如果单纯的交给Spring的IOC容器来实现会配置非常复杂有时甚至没办法实现。所以这种情况下Spring为我们提供了FactoryBean这个接口来实现这个创建的过程。

public interface FactoryBean<T> {
    //获取FactoryBean初始化的Bean实例
    T getObject() throws Exception;
    //获取Bean实例的类型
    Class<?> getObjectType();
    //判断是否是单例模式
    boolean isSingleton();
}

示例:

@Component
public class MyBean implements FactoryBean {
    private String message;
    public MyBean() {
        this.message = "通过构造方法初始化实例";
    }
    @Override
    public Object getObject() throws Exception {
        MyBean myBean = new MyBean();
        // 这里可以做一些复杂的操作,比如解析资源等IOC没办法实现的情况
        // 这里并不一定要返回MyBean自身的实例,可以是其他任何对象的实例如:SqlSessionFactory
        return myBean;
    }
    @Override
    public Class<?> getObjectType() {
        return MyBean.class;
    }
    @Override  
    public boolean isSingleton() {  
        return false;  
    } 
}

BeanFactory接口

BeanFactory有三个是子类:AutowireCapableBeanFactory,HierarchicalBeanFactory,ListableBeanFactory。最终的默认实现类是 DefaultListableBeanFactory

BeanFactory接口是Spring bean容器(也就是IoC容器)的核心根接口,主要是用于创建bean的工厂接口,其定义的接口方法分为以下几个部分:获取bean实例、判断容器中是否包含某个bean、判断实例是否为单列模式或则原型模式、类型匹配、实例类型、获取别名。

// 用于区分FactoryBean实例,列如:如果myJndiObject是一个FactoryBean,通过 &myJndiObject获取返回的是工厂,而不是工厂返回的实例。
String FACTORY_BEAN_PREFIX = "&";

// 获取bean
Object getBean(String name) throws BeansException;
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;

// 获取bean的提供者(对象工厂)
<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);
<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);

boolean containsBean(String name); // 是否包含指定名字的bean
boolean isSingleton(String name) throws NoSuchBeanDefinitionException; // 是否为单例
boolean isPrototype(String name) throws NoSuchBeanDefinitionException; // 是否为原型

// 指定名字的bean是否和指定的类型匹配
boolean isTypeMatch(String name, ResolvableType typeToMatch);
boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
Class<?> getType(String name) throws NoSuchBeanDefinitionException; // 获取指定名字的bean的类型
String[] getAliases(String name); // 获取指定名字的bean的所有别名

 BeanDefinition

管理每个bean的定义信息,容器启动的时候,spring会将配置文件中定以的信息或则使用注解(如@Componet @Service @Controller等)定义的bean封装成一个个 BeanDefinition 对象,每个bean对应一个BeanDefinition对象,在对象实例化期间,使用bean对应的BeanDenifition对象通过反射生成实例对象。BeanDefinition接口方法用来管理bean的属性信息。

BeanDefinition接口中的属性信息跟xml配置文件中的标签中的属性一一对应,也就是说一个BeanDefinition对应一个标签信息。在容器启动的时候,就会先将标签信息解析封装成BeanDefinition接口实现类对象。

BeanDefinition有一个子接口 AnnotatedBeanDefinition;三个间接实现类,分别是RootBeanFactory、ChildBeanFactory和GenericBeanDefinition。其中RootBeanFactory是用来封装父类定义信息(没有显示继承其他类的类)、ChildBeanDefinition是用来封装子类定义信息。

 BeanDefinitionRegistry接口

  定义了关于 BeanDefinition 的注册、移除、查询等一系列的操作。BeanDefinition 注册的容器为 DefaultListableBeanFactory下 beanDefinitionMap 

/** Map of bean definition objects, keyed by bean name. */
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

    /** Map from bean name to merged BeanDefinitionHolder. */
    private final Map<String, BeanDefinitionHolder> mergedBeanDefinitionHolders = new ConcurrentHashMap<>(256);

    /** Map of singleton and non-singleton bean names, keyed by dependency type. */
    private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64);

    /** Map of singleton-only bean names, keyed by dependency type. */
    private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<>(64);

    /** List of bean definition names, in registration order. */
    private volatile List<String> beanDefinitionNames = new ArrayList<>(256);

BeanDefinitionRegistryPostProcessor接口

BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的子接口,用于动态注册、修改、移除beanDefinitionMap的BeanDefinition

//修改应用程序上下文的内部bean定义注册表,在所有Bean定义将要被加载,Bean实例还未创建的时候运行,它优先于postProcessBeanFactory方法执行。
void    postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry);
public class test {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Appconfig.class);
    }
}
//自定义BeanDefinitionRegistryPostProcessor实现注册、移除、修改BeanDefinition
class CustomBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        System.out.println("---->postProcessBeanDefinitionRegistry容器中BeanDefinition的数量为:" + registry.getBeanDefinitionCount());
        RootBeanDefinition beanDefinition = new RootBeanDefinition(Person.class);
        // 还可以这样给容器中注册
     //Bean AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Dog.class).getBeanDefinition();
        registry.registerBeanDefinition("person", beanDefinition);
    }
   //这是继承父类BeanFactoryPostProcessor的方法
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
        for (String str : beanDefinitionNames) {
            System.out.println("----->" + str);
        }
        System.out.println("====>postProcessBeanFactory容器中BeanDefinition的数量为:" + beanFactory.getBeanDefinitionCount());
    }
}

@Component
class Appconfig {
    @Bean
    public CustomBeanDefinitionRegistryPostProcessor customBeanDefinitionRegistryPostProcessor() {
        return new CustomBeanDefinitionRegistryPostProcessor();
    }
} 

BeanFactoryPostProcessor接口

BeanFactoryPostProcessor允许修改容器中的BeanDefinitions ,但不允许触发Bean的实例化;这样做可能会导致bean实例化过早,从而违反了容器并造成了意外的副作用。如果需要bean实例交互,请使用BeanPostProcessor。

副作用1——使用注解进行依赖注入失败;

副作用2——可能会将ApplicationContext容器启动过程暴露在多线程之下;

可以配置多个BeanFactoryPostProcessor的实现类,通过”order”控制执行次序,值越大优先级越低(要实现Ordered接口)

//BeanFactoryPostProcessor是在 Bean定义加载完成之后,Bean实例初始化之前会调用postProcessBeanFactory方法
void    postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
public class test {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Appconfig.class);
        Person person = (Person)context.getBean("person");
        System.out.println(person.toString());
    }
}
@Component
public class Appconfig {
    @Bean
    public CustomBeanDefinitionRegistryPostProcessor customBeanDefinitionRegistryPostProcessor() {
        return new CustomBeanDefinitionRegistryPostProcessor();
    }
    @Bean
    public CustomBeanFactoryPostProcessor customBeanFactoryPostProcessor(){
        return new CustomBeanFactoryPostProcessor();
    }
    @Bean
    public Person person(){
        Person person = new Person();
        person.setName("张三");
        return person;
    }
}
public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        int count = beanFactory.getBeanDefinitionCount();
        String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
        for (String beanName : beanDefinitionNames) {
            if ("person".equals(beanName)) {
                BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
                MutablePropertyValues m = beanDefinition.getPropertyValues();
                m.addPropertyValue("name", "赵四");
                System.out.println("--修改了name属性初始值了");
            }
        }
    }
}
@Bean
public Person person(){
    Person person = new Person();
    person.setName("张三");
    return person;
}

BeanPostProcessor接口

SpringAOP代理就是作为BeanPostProcessor实现.

BeanPostProcessor主要是在初始化的前后处理相应的事,必须在普通对象创建之前被创建

可以配置多个BeanPostProcessor的实现类,通过”order”控制执行次序,值越大优先级越低(要实现Ordered接口)

先执行的是postProcessBeforeInitialization,然后是afterPropertiesSet,然后是init-method,然后是postProcessAfterInitialization。

//在任何bean初始化回调(如InitializingBean 或自定义init-method)之前
Object    postProcessBeforeInitialization(Object bean, String beanName)

//在任何bean初始化回调(如InitializingBean 或自定义init-method)之后
Object    postProcessAfterInitialization(Object bean, String beanName)
public class test {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Appconfig.class);
        Person person = (Person)context.getBean("person");
        System.out.println(person.toString());
    }
}
@Configuration
public class Appconfig {
    // 提示信息: is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
    // 对于返回Spring BeanFactoryPostProcessor(BFPP)类型或者BeanPostProcessor(BPP)类型的@Bean方法,必须特别注意。 
    // 因为BFPP对象必须在容器生命周期的早期实例化,所以它们会干扰@Configuration类中的@Autowired,@ Value和@PostConstruct之类的注释的处理。 
    // 为了避免这些生命周期问题,请将BFPP或BPP返回的@Bean方法标记为static
    @Bean
    public static CustomBeanPostProcessor customBeanPostProcessor(){
        return new CustomBeanPostProcessor();
    }
    
    @Bean
    public Person person(){
        Person person = new Person();
        person.setName("张三");
        return person;
    }
}
public class CustomBeanPostProcessor implements BeanPostProcessor {

    public CustomBeanPostProcessor() {
        System.out.println("CustomBeanPostProcessor 实例化......");
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("spring中bean实例:" + beanName + " 初始化之前处理......");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("spring中bean实例:" + beanName + " 初始化之后处理......");
        if ("person".equals(beanName)){
            Field[] declaredFields = bean.getClass().getDeclaredFields();
            for (Field declaredField : declaredFields) {
                if ("name".equals(declaredField.getName())){
                    try {
                        //修改对象的属性
                        declaredField.setAccessible(true);
                        declaredField.set(bean,"哈哈哈");
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return bean;
    }
}

注意点:

 (一)BeanPostProcessor依赖的bean,不会执行BeanPostProcessor的方法,因为所依赖的Bean需要在BeanPostProcessor之前创建完成!

   (二)BeanPostProcessor以及依赖的bean无法使用AOP!

 (三)当使用ConfigurableBeanFactory接口的addBeanPostProcessor方法手动添加BeanPostProcessor时,只能作用于那些延迟加载的Bean或非单例bean!

 (四)使用addBeanPostProcessor方式添加的BeanPostProcessor,Ordered接口的作用将失效,而是以注册的顺序执行!

 (五)在使用@Bean声明工厂方法返回BeanPostProcessor实现类对象时,返回值必须是BeanPostProcessor类型,或者更低级的类型!

InstantiationAwareBeanPostProcessor接口

InstantiationAwareBeanPostProcessor接口继承了BeanPostProcess接口,区别如下:

BeanPostProcess接口只在bean的初始化阶段进行扩展(注入spring上下文前后),而InstantiationAwareBeanPostProcessor接口在此基础上增加了3个方法,把可扩展的范围增加了实例化阶段和属性注入阶段

//实例化bean之前,如果该方法返回null,后面的方法都正常执行,如果不为null,则直接执行postProcessAfterInitialization方法,(实例化之后 和 初始化之前都不执行)
Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;
//实例化bean之后,如果该方法返回false,并且不需要check,那么postProcessProperties就会被忽略不执行;如果返回true,postProcessProperties就会被执行
boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;
//bean已经实例化完成,可以对属性值进行修改(这个时候属性值还未被设置,但是我们可以修改原本该设置进去的属性值)
PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException
public class Test {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Appconfig.class);
        Object person = context.getBean("person");
        System.out.println(person.toString());
    }
}
@Configuration
class Appconfig {
    @Bean
    public CustomInstantiationAwareBeanPostProcessor customInstantiationAwareBeanPostProcessor(){
        return new CustomInstantiationAwareBeanPostProcessor();
    }
    @Bean
    public Person person(){
        Person person = new Person();
        person.setName("张三");
        return person;
    }
}
public class CustomInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        System.out.println("--->postProcessBeforeInstantiation");//顺序1
        return null;
    }
    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        System.out.println("--->postProcessAfterInstantiation");//顺序2
        return true;
    }
    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        System.out.println("--->postProcessProperties");//顺序3
        return pvs;
    }
    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
        System.out.println("--->postProcessPropertyValues");
        return pvs;
    }
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("--->postProcessBeforeInitialization");//顺序4
        return bean;
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("--->postProcessAfterInitialization");//顺序5
        return bean;
    }
}

BeanFactoryAware接口

实现BeanFactoryAware接口可以直接访问 Spring 容器(BeanFactory)

//可以获取到Spring容器
void setBeanFactory(BeanFactory beanFactory) throws BeansException;
public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Appconfig.class);
        Object person = CustomBeanFactoryAware.getBean("person");
        System.out.println(person.toString());
    }
}
@Configuration
class Appconfig {
    @Bean
    public CustomBeanFactoryAware customBeanFactoryAware(){
        return new CustomBeanFactoryAware();
    }
    @Bean
    public Person person(){
        Person person = new Person();
        person.setName("张三");
        return person;
    }
}
public class CustomBeanFactoryAware implements BeanFactoryAware {
    private static BeanFactory bff;
    public static void setContextBean(BeanFactory bf){
        bff=bf;
    }
    public static Object getContextBean(String  beanName){
        return bff.getBean(beanName);
    }
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        CustomBeanFactoryAware.setContextBean(beanFactory);
    }
    public static Object getBean(String beanName){
        return CustomBeanFactoryAware.getContextBean(beanName);
    }
}

ApplicationContextAware接口

实现ApplicationContextAware接口可以直接获得Spring上下文管理器(ApplicationContext),使用方法参考BeanFactoryAware接口

EnvironmentAware接口

用于获取EnviromentAware一个扩展类,可以获得系统内的所有参数,使用方法参考BeanFactoryAware接口

ResourceLoaderAware接口

用于获取ResourceLoader的一个扩展类,获取classpath内所有的资源对象,使用方法参考BeanFactoryAware接口

EmbeddedValueResolverAware接口

用于获取StringValueResolver的一个扩展类,StringValueResolver用于获取基于String类型的properties的变量,使用方法参考BeanFactoryAware接口

MessageSourceAware接口

用于获取MessageSource的一个扩展类,MessageSource主要用来做国际化,使用方法参考BeanFactoryAware接口

ApplicationEventPublisherAware接口

用于获取ApplicationEventPublisher的一个扩展类,ApplicationEventPublisher可以用来发布事件,结合ApplicationListener来共同使用。

ApplicationContextInitializer接口

用于在spring容器refresh()刷新之前初始化Spring ConfigurableApplicationContext的回调接口,允许我们对ConfigurableApplicationContext的实例做进一步的设置和处理。例如,根据上下文环境注册属性源或激活配置文件等。

  • ApplicationContextInitializer支持Order注解,表示执行顺序,越小越早执行;
//初始化给定的应用程序上下文
void initialize(C applicationContext);
@Order(1)
class CustomApplicationContextInitializer implements ApplicationContextInitializer {
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        System.out.println("-----MyApplicationContextInitializer initialize-----");
        // 打印人所有 beanName
        System.out.println(applicationContext.getBeanDefinitionCount() + "个Bean的名字如下:");
        Arrays.stream(applicationContext.getBeanDefinitionNames()).forEach(System.out::println);
        //从容器中获取环境变量组件
        ConfigurableEnvironment environment = applicationContext.getEnvironment();
        //自己自定义一些属性放在map集合中
        Map<String, Object> map = new HashMap<>();
        map.put("key1", "value1");
        //包装为MapPropertySource组件
        MapPropertySource mapPropertySource = new MapPropertySource("firstInitializer", map);
        //存到环境变量中去
        environment.getPropertySources().addLast(mapPropertySource);
        System.out.println("FirstInitializer属性注册成功...");
     //注册后置处理器
     
applicationContext.addBeanFactoryPostProcessor(new CustomBeanDefinitionRegistryPostProcessor());
  }
}

三种实现方式:

①SpringBoot方式

@SpringBootApplication
public class SpringBootStudyApplication {
    public static void main(String[] args) {
        SpringApplication springApplication = new SpringApplication(SpringBootStudyApplication.class);
        //手动注册初始化器
        springApplication.addInitializers(new CustomApplicationContextInitializer());
        springApplication.run(args);
    }
}

②resources目录下新建application.properties方式

#initializer
context.initializer.classes = com.yue.config.CustomApplicationContextInitializer

③resources目录下新建META-INF/spring.factories方式

org.springframework.context.ApplicationContextInitializer = com.yue.config.CustomApplicationContextInitializer

SmartInitializingSingleton接口

可以对所有单例对象(非懒加载对象)初始化完毕后,做一些后置的业务处理。

CommandLineRunner / ApplicationRunner接口

整个项目启动完毕后,自动执行。如果有多个CommandLineRunner,可以利用@Order来进行排序。

posted @ 2020-10-16 18:26  柒月丶  阅读(465)  评论(0)    收藏  举报