Spring源码理解 类接口说明

FactoryBean、BeanFactory

BeanFactory

BeanFactory是管理和生产Bean的,它是用于访问Spring Bean容器的根接口。,定义了管理Bean的方法,获取Bean、包含Bean、是否单例Bean、获取Bean类型等。Spring根据他提供了很多实现,如 DefaultListableBeanFactoryXmlBeanFactoryApplicationContext等。其中XmlBeanFactory就是常用的一个,该实现将以XML方式描述组成应用的对象及对象间的依赖关系。AnnotationConfigApplicationContext类是基于组件类作为输入的Spring上下文入口,比如@Configuration注解标注的类和@ComponentScan标注的类

FactorBean

FactoryBean首先是一个Bean,其次他能生产Bean,它是某个Bean的工厂类,主要用于生产这个Bean

一般情况下,Spring通过反射机制利用的class属性指定实现类实例化Bean。至于为什么会有FactoryBean?

  1. 实例化Bean比较复杂,单纯使用反射受限,使用FactoryBean专门来创建具体的Bean。实例化Bean过程比较复杂,如果按照传统的方式,则需要在中提供大量的配置信息。配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。Spring为此提供了一个org.springframework.bean.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化Bean的逻辑
  2. 由于第三方库不能直接注册到spring容器,于是可以实现org.springframework.bean.factory.FactoryBean接口,然后给出自己对象的实例化代码即可

FactoryBean表现的是一个工厂的职责。 即一个Bean A如果实现了FactoryBean接口,那么A就变成了一个工厂,根据A的名称获取到的实际上是工厂调用getObject()返回的对象,而不是A本身,如果要获取工厂A自身的实例,那么需要在名称前面加上’&'符号。

  • getObject(’ name ')返回工厂中的实例
  • getObject(’ &name ')返回工厂本身的实例
源码

在refresh方法的finishBeanFactoryInitialization中,是为其他还没有实例化的Bean进行实例化。preInstantiateSingletons方法来实例化单例对象。在初始化Bean实例获取Bean的时候,会判断当前BeanDefinition当前的beanName是不是FactoryBean,如果是,则会先获取FactoryBean的实例。如果该工厂Bean实现了SmartFactoryBean(一般Spring框架内部使用),则会立刻初始化工厂Bean指向的Bean。

FactoryBean——Spring的扩展点之一 - 掘金 (juejin.cn)

Bean生命周期

  1. 根据Bean定义创建Bean的对象
  2. Bean对象创建完后,设置属性值的注入
  3. 为当前Bean调用所有BeanPostProcessor后置处理器的初始化前的方法,此时会设置ApplicationContextAware等各种Aware
  4. 调用初始化方法,比如InitializingBean接口的afterPropertiesSet方法,或者配置了initMethod方法
  5. 为当前Bean调用所有BeanPostProcessor后置处理器的初始化后的方法
  6. Bean添加到单例线程池中,被容器管理
  7. Bean实现了DisposableBean接口,执行destory方法或调用了声明destory-method的方法

Bean创建过程

test方法----…---->refresh()
---->finishBeanFactoryInitialization()
.
---->preInstantiateSingletons()
.
---->preInstantiateSingletons()
.
---->getBean()
.
---->doGetBean()
.
----> getSingleton(beanName, new ObjectFactory()
这是一个简单的流程,可以大致看一下在容器启动的时候具体调用了哪些方法;

我们先进入doGetBean方法里面:发现其实是调用了getSingleton方法获取实例,
如果没有获取到又通过getObject()里面的 createBean(beanName, mbd, args)创建实例,总之这个实例一定要创建出来

Bean创建循环依赖

Bean在创建过程中会把自己暴露出来。一个是初始化对象之后会提前暴露处来,添加到单例工厂集合中,Bean完全实例化创建后会添加到单例对象集合中,删除单例工厂集合和暴露对象集合。暴露出来后,其他Bean就可以获取这个Bean的实例。

而在当前Bean如果依赖其他没有实例化Bean的时候,也就是@Autowire注解标注了一个没有实例化的属性。这时会在Bean初始化Bean之前(后置处理器初始化前,初始化方法,后置处理器初始化后),进行属性注入,也就是populateBean(beanName, mbd, instanceWrapper)方法。其内部会有后置处理器AutowiredAnnotationBeanPostProcessor来处理,检查到标注的@Autowired属性B,获取他的Bean。如果它也依赖了A,就形成了循环依赖。

如果A注入了B,B中注入了A。那么会先初始化A,暴露单例工厂自身A,注入属性的时候检查到标注了自动注入注解,则会初始化B,暴露单例工厂自身B,B进行注入属性的时候检查到依赖了A,这个时候获取A的Bean就可以走循环依赖的三级缓存,从单例工厂中获取A的Bean,并添加到暴露单例对象中。当B的Bean创建完毕后,就完成A的Bean的属性注入了,就正常创建A的。Bean创建完之后会添加到singletonObjects中,后续直接获取。

为什么需要三级缓存,通过单例工厂来创建提前Bean?

首先他俩在内存中是同一个对象,其次是为了解决AOP切面代理问题。

getEarlyBeanReference这个方法主要逻辑大概描述下如果bean被AOP切面代理则返回的是beanProxy对象,如果未被代理则返回的是原bean实例

源码

bean的获取最先是从AbstractBeanFactory.doGetBean方法中开始。第一步就是直接获取单例对象,也就是从三级缓存(三个Map)中获取,Object sharedInstance = getSingleton(beanName);。主要是获取共享的单例Bean,也就是说共享暴露出来的。首先会从单例Bean集合(singletonObjects)中获取,获取不到就从早期暴露出Bean的集合(earlySingletonObjects)中获取,然后是从提前暴露的工厂对象中(singletonFactories)获取。如果在Bean实例集合或者提早暴露的中能获取的直接返回实例,否则看实例工厂有没有,有了就获取对象实例,并添加到暴露集合中。如果没有,最后就是空的。

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // Quick check for existing instance without full singleton lock
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        singletonObject = this.earlySingletonObjects.get(beanName);
        if (singletonObject == null && allowEarlyReference) {
            synchronized (this.singletonObjects) {
                // Consistent creation of early reference within full singleton lock
                singletonObject = this.singletonObjects.get(beanName);
                if (singletonObject == null) {
                    singletonObject = this.earlySingletonObjects.get(beanName);
                    if (singletonObject == null) {
                        ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                        if (singletonFactory != null) {
                            singletonObject = singletonFactory.getObject();
                            this.earlySingletonObjects.put(beanName, singletonObject);
                            this.singletonFactories.remove(beanName);
                        }
                    }
                }
            }
        }
    }
    return singletonObject;
}

如果Bean取不到就会创建Bean

创建Bean,如果有父容器则由父容器来创建Bean,没有了,则才会用当前子容器创建Bean。

获取Bean定义,判断是否有依赖的Bean,依赖的Bean有没有创建,如果没有创建就先创建依赖Bean,也是进入这个方法中创建Bean。dependentBeanMap中定义依赖的Bean集合

依赖Bean创建完之后会创建当前Bean。创建Bean会判断是单例的,原型的,获取其他的。进入单例的判断,创建Bean就是执行的createBean方法中创建的。

// 重载方法,第二次获取单例Bean,实际上根据createBean(beanName, mbd, args);创建
sharedInstance = getSingleton(beanName, () -> {
    try {
        return createBean(beanName, mbd, args);
    }
    catch (BeansException ex) {
        // Explicitly remove instance from singleton cache: It might have been put there
        // eagerly by the creation process, to allow for circular reference resolution.
        // Also remove any beans that received a temporary reference to the bean.
        destroySingleton(beanName);
        throw ex;
    }
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);

实际创建Bean的方法

内部调用Object beanInstance = doCreateBean(beanName, mbdToUse, args);在AbstractAutowireCapableBeanFactory类中,以下是实际创建Bean的方法签名。

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)

首先会根据反射或动态代理创建一个对象,将创建出来的对象构建成单例工厂,添加到三级缓存中。也就是单例工厂集合中,主要用于提前暴露自身。

boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
        isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
    if (logger.isTraceEnabled()) {
        logger.trace("Eagerly caching bean '" + beanName +
                "' to allow for resolving potential circular references");
    }
    // 三级缓存那块的三个集合,添加了提早暴露Bean Map earlySingletonObjects,单例工厂singletonFactories
    // SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference
    addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

然后会进行属性注入,也就是自动依赖注入,@Value、@Autowired的处理,如果有依赖对象,则会创建依赖的Bean。相当于又重新走了一遍创建Bean,如果这个时候发现了要注入的Bean依赖了A,就获取A这个Bean,那么A这个Bean就可以从三级缓存方法中获取。

后面,属性注入完成后,就初始化Bean的操作了。Bean初始化完成之后,就把Bean加入到一级缓存中了。后面直接从一级缓存中获取完成的Bean实例

BeanFactoryPostProcessor BeanDefinitionRegistryPostProcessor

BeanFactoryPostProcessor是在发生在bean实例化之前,BeanDefinition读取完之后。所以我们在这里可以获取到BeanDefinition,以改变他默认的实例化方式。

BeanDefinitionRegistryPostProcessor可以注册BeanDefinition。不但可以完全控制是否加入某个bean,动态加入某些bean,并且还可以控制bean的生成过程,比如像其直接注入属性等操作

实现逻辑和位置

AbstractApplicationContext类的invokeBeanFactoryPostProcessors方法就是处理实现了这两个后置处理器的类的,方法里会获取扫描到的类,并回调实现的方法。

BeanDefinitionRegistryPostProcessor扩展和BeanFactoryPostProcessor是在同一时间节点进行回调的,并且他的优先级是高于BeanFactoryPostProcessor,而他的作用是像spring容器中注册BeanDefinition。

首先是实现BeanDefinitionRegistryPostProcessor的类,会优先回调实现了PriorityOrdered接口的,然后进行排序再执行回调。然后是实现了Ordered接口的,然后排序后在执行回调,最后是其他的实现类,也会进行排序一下再执行回调。这里是直接回调postProcessBeanDefinitionRegistry方法了。等所有的都执行完了,才会统一回调postProcessBeanFactory方法。

随后才会获取实现BeanFactoryPostProcessor的类,依据顺序规则进行回调。

实现类

ApplicationContextAware ApplicationContextAwareProcessor

ApplicationContextAware接口主要用来注入容器实例的,就是ApplicationContext上下文的。

实现这个接口的类都可以通过,重写setApplicationContext方法得到参数列表上的ApplicationContext对象。

ApplicationContextAwareProcessor类是设置ApplicationContext对象的关键。他实现了BeanPostProcessor接口,重写方法postProcessBeforeInitialization里实现了其他的Spring内部对象,包括以下Aware接口。在实例化Bean(initializeBean)的时候都会执行BeanPostProcessor的操作

  • EnvironmentAware
  • EmbeddedValueResolverAware
  • ResourceLoaderAware
  • ApplicationEventPublisherAware
  • MessageSourceAware
  • ApplicationContextAware
  • ApplicationStartupAware

在Bean初始化后调用的AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization方法里会查询全部的BeanPostProcessor实例,然后依次将当前Bean和BeanName传入执行postProcessBeforeInitialization方法。

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    invokeAwareMethods(beanName, bean);

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        // 执行所有BeanPostProcessor的postProcessBeforeInitialization方法
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    try {
        invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
                (mbd != null ? mbd.getResourceDescription() : null), beanName, ex.getMessage(), ex);
    }
    if (mbd == null || !mbd.isSynthetic()) {
        // 执行所有BeanPostProcessor的postProcessAfterInitialization方法
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }

    return wrappedBean;
}

@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
        throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        Object current = processor.postProcessBeforeInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}

@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
        throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        Object current = processor.postProcessAfterInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}

BeanPostProcessor

后置处理器,作用是在Bean对象在实例化和依赖注入完毕后,在显示调用初始化方法的前后添加我们自己的逻辑。注意是Bean实例化完毕后及依赖注入完成后触发的。

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    invokeAwareMethods(beanName, bean);

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        // 执行postProcessBeforeInitialization
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    try {
        invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
                (mbd != null ? mbd.getResourceDescription() : null), beanName, ex.getMessage(), ex);
    }
    if (mbd == null || !mbd.isSynthetic()) {
        // 执行postProcessAfterInitialization
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }

    return wrappedBean;
}

所有实现了BeanPostProcessor的实现类都会在每个Bean初始化的时候执行一遍。因此内部很多实现了该接口的类都会判断一下当前Bean是不是某种类型的Bean,才会执行相关操作。例如ApplicationContextAwareProcessor

子类:

  • InitDestroyAnnotationBeanPostProcessor 处理初始化方法(我们初始化方法是如何执行的,如何被容器发现的,都是因为这个组件在工作,可在int-method打断点看看具体调试)
  • AutowiredAnnotationBeanPostProcessor 处理自动装配
  • BeanValidationPostProcessor
  • ApplicationContextAwareProcessor

SmartInitializingSingleton InitializingBean

SmartInitializingSingleton

在 Spring 容器中所有单例 Bean 初始化完成后执行一些自定义的初始化逻辑。当所有单例 Bean 的依赖关系都解析完毕,并且所有单例 Bean 的实例化与初始化过程完成后,Spring 容器会自动回调 SmartInitializingSingleton 接口的实现类的 afterSingletonsInstantiated() 方法。可以在该方法中编写自己的初始化逻辑。注意,这个方法只会被调用一次。

SmartInitializingSingleton 接口的使用场景通常是在所有单例 Bean 初始化完成后,希望执行一些需要考虑所有 Bean 依赖关系的初始化逻辑,例如进行缓存预热、启动一些定时任务等操作。

preInstantiateSingletons

// 为所有单例非懒加载的Bean触发初始化后回调...调用SmartInitializingSingleton接口的afterSingletonsInstantiated方法
for (String beanName : beanNames) {
    Object singletonInstance = getSingleton(beanName);
    if (singletonInstance instanceof SmartInitializingSingleton smartSingleton) {
        StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
                .tag("beanName", beanName);
        smartSingleton.afterSingletonsInstantiated();
        smartInitialize.end();
    }
}

事件机制

事件类型

  • ApplicationEvent 事件抽象类

  • ApplicationContextEvent 用于应用程序上下文的事件的基类

  • ContextStoppedEvent 当应用程序上下文停止时引发的事件

  • ContextRefreshedEvent 在ApplicationContext被初始化或刷新时引发的事件

  • ContextStartedEvent 当应用程序上下文启动时引发的事件

  • ContextClosedEvent 当应用程序上下文关闭时引发的事件

发布订阅,事件组播器

  • ApplicationEventMulticaster 接口由可以管理多个ApplicationListener对象的对象实现,并向它们发布事件

  • AbstractApplicationEventMulticaster 提供基本的侦听器注册功能

  • SimpleApplicationEventMulticaster 提供基本的侦听器注册功能,忽略它不感兴趣的事件

  • org.springframework.context.ApplicationEventPublisherAware 任何对象希望被其运行的ApplicationEventPublisher(通常是ApplicationContext)通知的任何对象实现的接口

  • EventPublicationInterceptor 事件发布拦截器

  • ApplicationEventPublisher 封装事件发布功能的接口

监听器

  • ApplicationListener
  • GenericApplicationListener
  • ApplicationListenerMethodAdapter

源码

初始化组播器

组播器收集所有监听器,并在接收到事件响应后匹配对应的监听器进行处理。

refresh方法中的initApplicationEventMulticaster方法会初始化事件组播器。首先会从BeanFactory中找是否已经有自定义的id为applicationEventMulticaster的Bean,有的话把它作为事件组播器。否则就初始化一个类型为SimpleApplicationEventMulticaster的

protected void initApplicationEventMulticaster() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
        this.applicationEventMulticaster =
                beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
        if (logger.isTraceEnabled()) {
            logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
        }
    }
    else {
        this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
        beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
        if (logger.isTraceEnabled()) {
            logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
                    "[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
        }
    }
}

注册监听器

refresh()方法的registerListeners()方法中,用于注册所有监听器。

找到所有实现了ApplicationListener接口的监听器类,并将其Bean名称添加到ApplicationEventMulticaster组播器实例的applicationListenerBeans集合中。

protected void registerListeners() {
    // 注册 已在容器中的(this.applicationListeners里的) 且已被初始化的ApplicationListener
    for (ApplicationListener<?> listener : getApplicationListeners()) {
        getApplicationEventMulticaster().addApplicationListener(listener);
    }

    // Do not initialize FactoryBeans here: We need to leave all regular beans
    // uninitialized to let post-processors apply to them!
    String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    for (String listenerBeanName : listenerBeanNames) {
        getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    }

    // 发布早期应用程序事件,现在我们终于有了多路广播...
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    this.earlyApplicationEvents = null;
    if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
        for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
            getApplicationEventMulticaster().multicastEvent(earlyEvent);
        }
    }
}

EventListenerMethodProcessor处理标注EventListener注解的方法为监听器并注册

EventListenerMethodProcessor类是查找监听器的,它实现了BeanFactoryPostProcessor和SmartInitializingSingleton来做这件事。这个类的Bean名为org.springframework.context.event.internalEventListenerProcessor,最初源自AnnotationConfigUtils.registerAnnotationConfigProcessors。他在代码第一行new上下文的时候的构造函数里就已经加到BeanDefinition中了。

因为实现了BeanFactoryPostProcessor,所以它早在invokeBeanFactoryPostProcessors的时候就已经创建了Bean。然后在refresh()中的finishBeanFactoryInitialization()中才开始执行afterSingletonsInstantiated()方法。

processBean()方法中具体处理了相关内容。扫描到有标注EventListener注解的类,根据目标类Class,方法Method和Bean名称,使用事件监听工厂创建监听器对象。并将其添加到SpringContext上下文的监听器列表和ApplicationEventMulticaster组播器中的集合中

// 有方法标注了,则根据监听所在方法注册成监听器对象,添加到组播器中
ConfigurableApplicationContext context = this.applicationContext;
Assert.state(context != null, "No ApplicationContext set");
// 获取默认的监听器工厂
List<EventListenerFactory> factories = this.eventListenerFactories;
Assert.state(factories != null, "EventListenerFactory List not initialized");
// 循环多个监听方法和多个监听器工厂,根据不同的监听器工厂创建多个监听器对象
for (Method method : annotatedMethods.keySet()) {
    for (EventListenerFactory factory : factories) {
        // 根据监听器工厂判断被监听非方法是否满足要求
        if (factory.supportsMethod(method)) {
            // 把这个方法转为一个可以执行的方法(主要和访问权限有关)
            Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName));
            // 根据监听器工厂创建监听器实例
            ApplicationListener<?> applicationListener =
                    factory.createApplicationListener(beanName, targetType, methodToUse);
            // 如果是ApplicationListenerMethodAdapter实例,则进行初始化。默认工厂DefaultEventListenerFactory创建的就是这个实例
            if (applicationListener instanceof ApplicationListenerMethodAdapter) {
                ((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator);
            }
            // 将监听器实例添加到spring上下,同时会添加到组播器中
            context.addApplicationListener(applicationListener);
            break;
        }
    }
}

发布事件

context.publishEvent(new AddEvent("-123"));

其中 invokeListener 方法中就调用了ApplicationEvent的onApplicationEvent方法了。

protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
    Assert.notNull(event, "Event must not be null");

    // 将推送的参数转换为ApplicationEvent
    ApplicationEvent applicationEvent;
    if (event instanceof ApplicationEvent applEvent) {
        applicationEvent = applEvent;
    }
    else {
        applicationEvent = new PayloadApplicationEvent<>(this, event, eventType);
        if (eventType == null) {
            eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
        }
    }

    // Multicast right now if possible - or lazily once the multicaster is initialized
    if (this.earlyApplicationEvents != null) {
        this.earlyApplicationEvents.add(applicationEvent);
    }
    else {
        // 执行事件的推送操作
        getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
    }

    // 如果当前容器有父容器,则也会调用父容器的事件推送
    if (this.parent != null) {
        if (this.parent instanceof AbstractApplicationContext abstractApplicationContext) {
            abstractApplicationContext.publishEvent(event, eventType);
        }
        else {
            this.parent.publishEvent(event);
        }
    }
}

public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
    ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
    Executor executor = getTaskExecutor();
    for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
        if (executor != null) {
            executor.execute(() -> invokeListener(listener, event));
        }
        else {
            invokeListener(listener, event);
        }
    }
}

在循环监听器中获取监听器列表方法使用了缓存的功能getApplicationListeners(event, type)

【Spring源码】事件监听机制全解_spring事件监听获取返回值-CSDN博客

动态注册Bean

可根据注解的方式,动态注入bean,而不需要显式根据Componment等注解。一般都是第三方库采用这种方式,比如Mybatis,使用的MapperScannerRegistrar类,对应的依赖注解就是@MapperScan。

使用ImportBeanDefinitionRegistrar接口可以实现,一般结合@Import注解和@Configuration注解。所有实现了该接口的类的都会被ConfigurationClassPostProcessor处理,ConfigurationClassPostProcessor实现了BeanFactoryPostProcessor接口,所以ImportBeanDefinitionRegistrar中动态注册的bean是优先与依赖其的bean初始化的,也能被aop、validator等机制处理。

动态注册Bean,其目的就是将扫描到的Bean添加到BeanFactory实例 IOC容器中,一般添加为单例Bean。

示例

以类似OpenFeign的Http调用的方式的示例来使用这个。实现细节为定义一个接口类为Http接口集合,每个方法为请求方法,根据请求注解配置相关请求地址等属性进行远程调用。即将接口类注入到Ioc容器中,依据动态代理的方式代理接口类,代理类处理每个方法进行业务处理。

而当前实现动态注册Bean只是将在Http接口集合所在的类注册Bean,通过注解扫描的方式动态注册。

我们需要定义如下类:

  • 定义类似@MapperScan注解的开关扫描注解, EnableHttpUtil.java
  • 定义的MapperScan注解中引入的MapperScannerRegistrar类,也就是实现ImportBeanDefinitionRegistrar接口类,此处为 HttpBeanRegistrar.java
  • 定义@HttpUtil注解,被该注解标注的类就是需要动态注册的Bean。当然也可以不扫描被该注解标注的,只要是根据扫描配置类扫描到就行。
  • 以上其实就可以完成动态注册Bean了。但实际注册Bean之后,后续还要处理更多的业务。比如扫描到Mapper接口类的方法可以直接调用。
  • 接下来类似OpenFeign的方式,定义方法上的调用注解HttpRequest.java
  • 业务处理类,发送http请求类 DemoHttpHandler.java
  • 定义某个被扫描业务使用接口, IRequestDemo.java
注解类
// 开关扫描类
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import(HttpBeanRegistrar.class)
public @interface EnableHttpUtil {
}
// 请求方法类型枚举
public enum HTTPMethod {
	GET,POST,PUT,DELETE
}
// 请求方法注解,标注在方法上
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface HttpRequest {
	HTTPMethod httpMethod() default HTTPMethod.GET;
	String url();
}
// Http工具类,标注在类上,类似FeignClient
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
public @interface HttpUtil {
}

HttpBeanRegistrar
/**
 * 动态Bean注入类,在ConfigurationClassPostProcessor中会被处理到
 */
public class HttpBeanRegistrar implements ImportBeanDefinitionRegistrar,
        ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, BeanClassLoaderAware {


    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        registerHttpRequest(registry);
    }

    /**
     * 动态注册Bean方法
     *
     * @param registry
     */
    private void registerHttpRequest(BeanDefinitionRegistry registry) {
        // 构建扫描类
        ClassPathScanningCandidateComponentProvider classPathBeanDefinitionScanner = getClassScanner();
        classPathBeanDefinitionScanner.setResourceLoader(this.resourceLoader);
        // 设置只扫描HttpUtil注解的类
        AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter(HttpUtil.class);
        classPathBeanDefinitionScanner.addIncludeFilter(annotationTypeFilter);
        // 定义扫描包
        String basePackage = "com.cgq.dynamicbean";
        Set<BeanDefinition> candidateComponents = classPathBeanDefinitionScanner.findCandidateComponents(basePackage);
        for (BeanDefinition beanDefinition : candidateComponents) {
            if (beanDefinition instanceof AnnotatedBeanDefinition) {
                registerBeans(((AnnotatedBeanDefinition) beanDefinition));
            }
        }

    }

    /**
     * 构造Class扫描器,设置了只扫描顶级接口,不扫描内部类
     *
     * @return
     */
    private ClassPathScanningCandidateComponentProvider getClassScanner() {
        return new ClassPathScanningCandidateComponentProvider(false, this.environment) {

            @Override
            protected boolean isCandidateComponent(
                    AnnotatedBeanDefinition beanDefinition) {
                if (beanDefinition.getMetadata().isInterface()) {
                    try {
                        Class<?> target = ClassUtils.forName(
                                beanDefinition.getMetadata().getClassName(),
                                classLoader);
                        return !target.isAnnotation();
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
                return false;
            }
        };
    }

    /**
     * 注册Bean方法,根据Bean定义对象获取Bean的类型,并创建该对象的代理
     *
     * @param beanDefinition
     */
    private void registerBeans(AnnotatedBeanDefinition beanDefinition) {
        String className = beanDefinition.getBeanClassName();
        ((DefaultListableBeanFactory) this.beanFactory).registerSingleton(className, createProxy(beanDefinition));
    }

    /**
     * 创建代理类,内部处理请求Http的逻辑
     *
     * @param beanDefinition
     * @return
     */
    private Object createProxy(AnnotatedBeanDefinition beanDefinition) {
        try {
            AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();
            Class<?> target = Class.forName(annotationMetadata.getClassName());
            InvocationHandler invocationHandler = createInvocationHandler();
            Object proxy = Proxy.newProxyInstance(HttpRequest.class.getClassLoader(), new Class[]{target}, invocationHandler);
            return proxy;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private InvocationHandler createInvocationHandler() {

        return new InvocationHandler() {
            private DemoHttpHandler demoHttpHandler = new DemoHttpHandler();

            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                return demoHttpHandler.handle(method);
            }
        };
    }

    private ResourceLoader resourceLoader;

    private BeanFactory beanFactory;

    private ClassLoader classLoader;
    private Environment environment;

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }

    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        this.classLoader = classLoader;
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }
}
DemoHttpHandler
/**
 * 定义业务处理类来处理注解标注的地址,并进行真实的http请求
 */
public class DemoHttpHandler {
	/**
	 * 实际业务调用处理
	 * @param method
	 * @return
	 */
	public HttpResult<?> handle(Method method) {
		HttpRequest request = method.getAnnotation(HttpRequest.class);
		String url = request.url();
		String methodName = request.httpMethod().name();
		String str = String.format("http request: url=%s and method=%s", url, methodName);
		return new HttpResult<String>(str, 200);
	}
}
IRequestDemo
@HttpUtil
public interface IRequestDemo {
	//调用test1时,会对http://abc.com发送get请求
	@HttpRequest(url = "http://abc.com")
	HttpResult<String> test1();
	//调用test2时,会对http://test2.com发送post请求
	@HttpRequest(url = "http://test2.com")
	HttpResult<String> test2();
}

HttpResult
public class HttpResult<T> {

	private String result;
	private int status;

	public HttpResult() {
	}

	public HttpResult(String result, int status) {
		this.result = result;
		this.status = status;
	}

	@Override
	public String toString() {
		return "HttpResult{" +
				"result='" + result + '\'' +
				", status=" + status +
				'}';
	}
}
Application
@EnableHttpUtil
@SpringBootApplication
public class DynamicBeanImportApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(DynamicBeanImportApplication.class, args);

        IRequestDemo bean = run.getBean(IRequestDemo.class);
        HttpResult<String> stringHttpResult = bean.test1();
        System.out.println(stringHttpResult);
    }
}

动态注册bean,Spring官方套路:使用ImportBeanDefinitionRegistrar - 知乎 (zhihu.com)

依赖注入 DI 控制反转Ioc

控制反转和依赖注入的理解(通俗易懂)-CSDN博客

Ioc

Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。

  • 谁控制谁,控制什么:传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对 象的创建;*谁控制谁?当然是IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)*
  • 为何是反转,哪些方面反转了:有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。

是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序

DI

组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。**依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。**通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。

总结

IoC和DI由什么关系呢?其实它们是同一个概念的不同角度描述,由于控制反转概念比较含糊(可能只是理解为容器控制对象这一个层面,很难让人想到谁来维护对象关系),所以2004年大师级人物Martin Fowler又给出了一个新的名字:“依赖注入”,相对IoC 而言,“依赖注入”明确描述了“被注入对象依赖IoC容器配置依赖对象”。

所以控制反转IoC(Inversion of Control)是说创建对象的控制权进行转移,以前创建对象的主动权和创建时机是由自己把控的,而现在这种权力转移到第三方,比如转移交给了IoC容器,它就是一个专门用来创建对象的工厂,你要什么对象,它就给你什么对象,有了 IoC容器,依赖关系就变了,原先的依赖关系就没了,它们都依赖IoC容器了,通过IoC容器来建立它们之间的关系。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值