前言

Spring是一款非常强大的框架,可以说是几乎所有的企业级Java项目使用了Spring,而Bean又是Spring框架的核心。

Spring框架运用了非常多的设计模式,从整体上看,它的设计严格遵循了OCP—-开闭原则,即:

1、保证对修改关闭,即外部无法修改Spring整个运作的流程

2、提供对扩展开放,即可以通过继承、实现Spring提供的众多抽象类与接口来改变类加载的行为

开卷有益,阅读Spring源码(无需每个类都看得很细,大体流程能梳理出来即可)对于个人水平的提升是帮助非常大的,同时也能在工作中即使发现和解决一些不常见的Spring问题。

不过,本文的目的不是整理Spring的流程,而是通过介绍一些常用的Spring Bean工具类,来让我们可以更好地使用Spring提供给开发者的多种特性,下面让我们开始吧。

InitialingBean和DisposableBean

InitialingBean是一个接口,提供了一个唯一的方法afterPropertiesSet()。

DisposableBean也是一个接口,提供了一个唯一的方法destory()。

这两个接口是一组的,功能类似,因此放在一起:前者顾名思义在Bean属性都设置完毕后调用afterPropertiesSet()方法做一些初始化的工作,后者在Bean生命周期结束前调用destory()方法做一些收尾工作。下面看一下例子,为了能明确地知道afterPropertiesSet()方法的调用时机,加上一个属性,给属性set方法,在set方法中打印一些内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**
 * @author 五月的仓颉 http://www.cnblogs.com/xrq730/p/5721366.html
 */
publicclass LifecycleBean implementsInitializingBean, DisposableBean
{
    @SuppressWarnings("unused")
    privateString    lifeCycleBeanName;
    publicvoid setLifeCycleBeanName(String lifeCycleBeanName)
    {
        System.out.println("Enter LifecycleBean.setLifeCycleBeanName(), lifeCycleBeanName = " + lifeCycleBeanName);
        this.lifeCycleBeanName = lifeCycleBeanName;
    }
    publicvoid destroy() throwsException
    {
        System.out.println("Enter LifecycleBean.destroy()");
    }
    publicvoid afterPropertiesSet() throwsException
    {
        System.out.println("Enter LifecycleBean.afterPropertiesSet()");
    }
    publicvoid beanStart()
    {
        System.out.println("Enter LifecycleBean.beanStart()");
    }
    publicvoid beanEnd()
    {
        System.out.println("Enter LifecycleBean.beanEnd()");
    }
}

配置一个spring.xml:

1
2
3
4
5
6
7
8
9
10
11
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">
    <beanid="lifeCycleBean"class="org.xrq.bean.lifecycle.LifecycleBean">
        <propertyname="lifeCycleBeanName"value="lifeCycleBean"/>
    </bean>
</beans>

启动Spring容器,LifecycleBean执行的结果为:

1
2
3
4
5
Enter LifecycleBean.setLifeCycleBeanName(), lifeCycleBeanName = lifeCycleBean
Enter LifecycleBean.afterPropertiesSet()
Enter LifecycleBean.beanStart()
Enter LifecycleBean.destroy()
Enter LifecycleBean.beanEnd()

执行结果和我们想的一样,afterPropertiesSet()方法就如同它的名字所表示的那样,是在Bean的属性都被设置完毕之后,才会调用。

关于这两个接口,我总结几点:

1、InitializingBean接口、Disposable接口可以和init-method、destory-method配合使用,接口执行顺序优先于配置

2、InitializingBean接口、Disposable接口底层使用类型强转.方法名()进行直接方法调用,init-method、destory-method底层使用反射,前者和Spring耦合程度更高但效率高,后者解除了和Spring之间的耦合但是效率低,使用哪个看个人喜好

3、afterPropertiesSet()方法是在Bean的属性设置之后才会进行调用,某个Bean的afterPropertiesSet()方法执行完毕才会执行下一个Bean的afterPropertiesSet()方法,因此不建议在afterPropertiesSet()方法中写处理时间太长的方法

BeanNameAware、ApplicationContextAware和BeanFactoryAware

这三个接口放在一起写,是因为它们是一组的,作用相似。

“Aware”的意思是”感知到的”,那么这三个接口的意思也不难理解:

1、实现BeanNameAware接口的Bean,在Bean加载的过程中可以获取到该Bean的id

2、实现ApplicationContextAware接口的Bean,在Bean加载的过程中可以获取到Spring的ApplicationContext,这个尤其重要,ApplicationContext是Spring应用上下文,从ApplicationContext中可以获取包括任意的Bean在内的大量Spring容器内容和信息

3、实现BeanFactoryAware接口的Bean,在Bean加载的过程中可以获取到加载该Bean的BeanFactory

看一下例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/**
 * @author 五月的仓颉 http://www.cnblogs.com/xrq730/p/5721366.html
 */
publicclass AwareBean implementsBeanNameAware, BeanFactoryAware, ApplicationContextAware
{
    privateString                     beanName;
    privateApplicationContext        applicationContext;
    privateBeanFactory                beanFactory;
    publicvoid setBeanName(String beanName)
    {
        System.out.println("Enter AwareBean.setBeanName(), beanName = " + beanName + "\n");
        this.beanName = beanName;
    }
    publicvoid setApplicationContext(ApplicationContext applicationContext) throwsBeansException
    {
        System.out.println("Enter AwareBean.setApplicationContext(), applicationContext = " + applicationContext + "\n");
        this.applicationContext = applicationContext;
    }
    publicvoid setBeanFactory(BeanFactory beanFactory) throwsBeansException
    {
        System.out.println("Enter AwareBean.setBeanFactory(), beanfactory = " + beanFactory + "\n");
        this.beanFactory = beanFactory;
    }
}

配置一个Spring.xml:

1
2
3
4
5
6
7
8
9
10
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">
    <beanid="AwareBean"class="org.xrq.bean.aware.AwareBean"/>
</beans>

启动Spring容器后的执行结果为:

1
2
3
4
5
Enter AwareBean.setBeanName(), beanName = AwareBean
Enter AwareBean.setBeanFactory(), beanfactory = org.springframework.beans.factory.support.DefaultListableBeanFactory@2747fda0: defining beans [AwareBean,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor,org.springframework.context.annotation.ConfigurationClassPostProcessor.enhancedConfigurationProcessor]; root of factory hierarchy
Enter AwareBean.setApplicationContext(), applicationContext = org.springframework.context.support.GenericApplicationContext@5514cd80: startup date [Mon Aug 08 19:23:30 CST 2016]; root of context hierarchy

关于这三个接口以及上面的打印信息,总结几点:

1、如果你的BeanName、ApplicationContext、BeanFactory有用,那么就自己定义一个变量将它们保存下来,如果没用,那么只需要实现setXXX()方法,用一下Spring注入进来的参数即可

2、如果Bean同时还实现了InitializingBean,容器会保证BeanName、ApplicationContext和BeanFactory在调用afterPropertiesSet()方法被注入

FactoryBean

FactoryBean在Spring中是非常有用的,使用Eclipse/MyEclipse的朋友可以对FactoryBean使用ctrl+t查看一下,FactoryBean这个接口在Spring容器中有大量的子实现。

传统的Spring容器加载一个Bean的整个过程,都是由Spring控制的,换句话说,开发者除了设置Bean相关属性之外,是没有太多的自主权的。FactoryBean改变了这一点,开发者可以个性化地定制自己想要实例化出来的Bean,方法就是实现FactoryBean接口。

看一下代码例子,为了讲清楚FactoryBean,内容相对多一些,首先定义一个接口Animal:

1
2
3
4
publicinterface Animal
{
    publicvoid move();
}

定义两个实现类Monkey和Tiger:

1
2
3
4
5
6
7
publicclass Monkey implementsAnimal
{
    publicvoid move()
    {
        System.out.println("Monkey move!");
    }
}

1
2
3
4
5
6
7
publicclass Tiger implementsAnimal
{
    publicvoid move()
    {
        System.out.println("Tiger move!");
    }
}

写一个实现类,实现FactoryBean接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/**
 * @author 五月的仓颉 http://www.cnblogs.com/xrq730/p/5721366.html
 */
publicclass AnimalFactoryBean implementsFactoryBean<Animal>
{
    privateString    animal;
    publicAnimal getObject() throwsException
    {
        if("Monkey".equals(animal))
        {
            returnnew Monkey();
        }
        elseif ("Tiger".equals(animal))
        {
            returnnew Tiger();
        }
        else
        {
            returnnull;
        }
    }
    publicClass<?> getObjectType()
    {
        returnAnimal.class;
    }
    publicboolean isSingleton()
    {
        returntrue;
    }
    publicvoid setAnimal(String animal)
    {
        this.animal = animal;
    }
}

配置一个spring.xml,注入属性Tiger:

1
2
3
4
5
6
7
8
9
10
11
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">
    <beanid="animal"class="org.xrq.bean.factory.AnimalFactoryBean">
        <propertyname="animal"value="Tiger"/>
    </bean>   
</beans>

写一个JUnit的测试类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
        "classpath*:spring.xml",
})
publicclass BaseTest
{
    @Resource
    privateAnimal    animal;
    @Test
    publicvoid aa()
    {
        animal.move();
    }
}

查看一下运行结果:

1
Tiger move!

看到最后得到的并不是FactoryBean本身,而是FactoryBean的泛型对象,这就是FactoryBean的作用。FactoryBean的几个方法:

1、getObject()方法是最重要的,控制Bean的实例化过程

2、getObjectType()方法获取接口返回的实例的class

3、isSingleton()方法获取该Bean是否为一个单例的Bean

像我这段代码的功能就是传入一个String类型的参数,可以动态控制生成出来的是接口的哪种子类。有了FactoryBean,同样的我们也可以灵活地操控Bean的生成。

BeanPostProcessor

之前的InitializingBean、DisposableBean、FactoryBean包括init-method和destory-method,针对的都是某个Bean控制其初始化的操作,而似乎没有一种办法可以针对每个Bean的生成前后做一些逻辑操作,PostProcessor则帮助我们做到了这一点,先看一个简单的BeanPostProcessor。

网上有一张图画了Bean生命周期的过程,画得挺好,原图出处:

BeanPostProcess接口有两个方法,都可以见名知意:

1、postProcessBeforeInitialization:在初始化Bean之前

2、postProcessAfterInitialization:在初始化Bean之后

值得注意的是,这两个方法是有返回值的,不要返回null,否则getBean的时候拿不到对象。

写一段测试代码,首先定义一个普通的Bean,为了后面能区分,给Bean加一个属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
publicclass CommonBean
{
    privateString commonName;
    publicvoid setCommonName(String commonName)
    {
        this.commonName = commonName;
    }
    publicvoid initMethod()
    {
        System.out.println("Enter CommonBean.initMethod(), commonName = " + commonName);
    }
}

定义一个PostProcess,实现BeanPostProcess接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
 * @author 五月的仓颉 http://www.cnblogs.com/xrq730/p/5721366.html
 */
publicclass PostProcessorBean implementsBeanPostProcessor
{
    publicObject postProcessAfterInitialization(Object bean, String beanName) throwsBeansException
    {
        System.out.println("Enter ProcessorBean.postProcessAfterInitialization()\n");
        returnbean;
    }
    publicObject postProcessBeforeInitialization(Object bean, String beanName) throwsBeansException
    {
        System.out.println("Enter ProcessorBean.postProcessBeforeInitialization()");
        returnbean;
    }
}

配置一个spring.xml,给CommonBean的commonName赋予不同的值以区分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">
    <beanid="common0"class="org.xrq.bean.common.CommonBean"init-method="initMethod">
        <propertyname="commonName"value="common0"/>
    </bean>
    <beanid="common1"class="org.xrq.bean.common.CommonBean"init-method="initMethod">
        <propertyname="commonName"value="common1"/>
    </bean>
    <beanid="postProcessorBean"class="org.xrq.bean.processor.PostProcessorBean"/>
</beans>

运行一个Spring容器, 初始化结果为:

1
2
3
4
5
6
7
8
9
10
Enter ProcessorBean.postProcessBeforeInitialization()
Enter CommonBean.initMethod(), commonName = common0
Enter ProcessorBean.postProcessAfterInitialization()
Enter ProcessorBean.postProcessBeforeInitialization()
Enter CommonBean.initMethod(), commonName = common1
Enter ProcessorBean.postProcessAfterInitialization()
Enter ProcessorBean.postProcessBeforeInitialization()
Enter ProcessorBean.postProcessAfterInitialization()

看到每个Bean初始化前后都会分别执行postProcessorBeforeInitiallization()方法与postProcessorAfterInitialization()方法,最后两行出现原因是,PostProcessorBean本身也是一个Bean。

BeanFactoryPostProcessor

接下来看另外一个PostProcessor—-BeanFactoryPostProcessor。

Spring允许在Bean创建之前,读取Bean的元属性,并根据自己的需求对元属性进行改变,比如将Bean的scope从singleton改变为prototype,最典型的应用应当是PropertyPlaceholderConfigurer,替换xml文件中的占位符,替换为properties文件中相应的key对应的value,这将会在下篇文章中专门讲解PropertyPlaceholderConfigurer的作用及其原理。

BeanFactoryPostProcessor就可以帮助我们实现上述的功能,下面来看一下BeanFactoryPostProcessor的使用,定义一个BeanFactoryPostProcessor的实现类:

1
2
3
4
5
6
7
8
9
10
11
/**
 * @author 五月的仓颉 http://www.cnblogs.com/xrq730/p/5721366.html
 */
publicclass FactoryPostProcessorBean implementsBeanFactoryPostProcessor
{
    publicvoid postProcessBeanFactory(ConfigurableListableBeanFactory configurablelistablebeanfactory)
            throwsBeansException
    {
        System.out.println("Enter FactoryPostProcessorBean.postProcessBeanFactory()\n");
    }
}

spring.xml里面配置一下这个Bean,就不写了,运行一下Spring容器,结果为:

1
2
3
4
5
6
7
8
9
10
11
12
Enter FactoryPostProcessorBean.postProcessBeanFactory()
Enter ProcessorBean.postProcessBeforeInitialization()
Enter CommonBean.initMethod(), commonName = common0
Enter ProcessorBean.postProcessAfterInitialization()
Enter ProcessorBean.postProcessBeforeInitialization()
Enter CommonBean.initMethod(), commonName = common1
Enter ProcessorBean.postProcessAfterInitialization()
Enter ProcessorBean.postProcessBeforeInitialization()
Enter ProcessorBean.postProcessAfterInitialization()

从执行结果中可以看出两点:

1、BeanFactoryPostProcessor的执行优先级高于BeanPostProcessor

2、BeanFactoryPostProcessor的postProcessBeanFactory()方法只会执行一次

注意到postProcessBeanFactory方法是带了参数ConfigurableListableBeanFactory的,这就和我之前说的可以使用BeanFactoryPostProcessor来改变Bean的属性相对应起来了。ConfigurableListableBeanFactory功能非常丰富,最基本的,它携带了每个Bean的基本信息,比如我简单写一段代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
 * @author 五月的仓颉 http://www.cnblogs.com/xrq730/p/5721366.html
 */
publicvoid postProcessBeanFactory(ConfigurableListableBeanFactory configurablelistablebeanfactory)
            throwsBeansException
{
    BeanDefinition beanDefinition = configurablelistablebeanfactory.getBeanDefinition("common0");
    MutablePropertyValues beanProperty = beanDefinition.getPropertyValues();
    System.out.println("scope before change:" + beanDefinition.getScope());
    beanDefinition.setScope("singleton");
    System.out.println("scope after change:" + beanDefinition.getScope());
    System.out.println("beanProperty:"+ beanProperty);
}

看一下执行结果:

1
2
3
scope before change:
scope after change:singleton
beanProperty:PropertyValues: length=1; bean property 'commonName'

这样就获取了Bean的生命周期以及重新设置了Bean的生命周期。ConfigurableListableBeanFactory还有很多的功能,比如添加BeanPostProcessor,可以自己去查看。

InstantiationAwareBeanPostProcessor

最后写一个叫做InstantiationAwareBeanPostProcessor的PostProcessor。

InstantiationAwareBeanPostProcessor又代表了Spring的另外一段生命周期:实例化。先区别一下Spring Bean的实例化和初始化两个阶段的主要作用:

1、实例化—-实例化的过程是一个创建Bean的过程,即调用Bean的构造函数,单例的Bean放入单例池中

2、初始化—-初始化的过程是一个赋值的过程,即调用Bean的setter,设置Bean的属性

之前的BeanPostProcessor作用于过程(2)前后,现在的InstantiationAwareBeanPostProcessor则作用于过程(1)前后,看一下代码,给前面的CommonBean加上构造函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
publicclass CommonBean
{
    publicCommonBean()
    {
        System.out.println("Enter CommonBean's constructor");
    }
    privateString commonName;
    publicvoid setCommonName(String commonName)
    {
        System.out.println("Enter CommonBean.setCommonName(), commonName = " + commonName);
        this.commonName = commonName;
    }
    publicvoid initMethod()
    {
        System.out.println("Enter CommonBean.initMethod(), commonName = " + commonName);
    }
}

实现InstantiationAwareBeanPostProcessor接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
 * @author 五月的仓颉 http://www.cnblogs.com/xrq730/p/5721366.html
 */
publicclass InstantiationAwareBeanPostProcessorBean implementsInstantiationAwareBeanPostProcessor
{
    publicObject postProcessAfterInitialization(Object bean, String beanName) throwsBeansException
    {
        System.out.println("Enter InstantiationAwareBeanPostProcessorBean.postProcessAfterInitialization()");
        returnbean;
    }
    publicObject postProcessBeforeInitialization(Object bean, String beanName) throwsBeansException
    {
        System.out.println("Enter InstantiationAwareBeanPostProcessorBean.postProcessBeforeInitialization()");
        returnbean;
    }
    publicboolean postProcessAfterInstantiation(Object bean, String beanName) throwsBeansException
    {
        System.out.println("Enter InstantiationAwareBeanPostProcessorBean.postProcessAfterInstantiation()");
        returntrue;
    }
    publicObject postProcessBeforeInstantiation(Class<?> bean, String beanName) throwsBeansException
    {
        System.out.println("Enter InstantiationAwareBeanPostProcessorBean.postProcessBeforeInstantiation()");
        returnnull;
    }
    publicPropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pd, Object bean,
            String beanName) throwsBeansException
    {
        returnpvs;
    }
}

配置一下spring.xml:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">
    <beanid="common"class="org.xrq.bean.common.CommonBean">
        <propertyname="commonName"value="common"/>
    </bean>
    <beanclass="org.xrq.bean.processor.InstantiationAwareBeanPostProcessorBean"/>
</beans>

启动容器,观察一下运行结果为:

1
2
3
4
5
6
7
8
9
Enter InstantiationAwareBeanPostProcessorBean.postProcessBeforeInstantiation()
Enter CommonBean's constructor
Enter InstantiationAwareBeanPostProcessorBean.postProcessAfterInstantiation()
Enter CommonBean.setCommonName(), commonName = common
Enter InstantiationAwareBeanPostProcessorBean.postProcessBeforeInitialization()
Enter InstantiationAwareBeanPostProcessorBean.postProcessAfterInitialization()
Enter InstantiationAwareBeanPostProcessorBean.postProcessAfterInstantiation()
Enter InstantiationAwareBeanPostProcessorBean.postProcessBeforeInitialization()
Enter InstantiationAwareBeanPostProcessorBean.postProcessAfterInitialization()

最后三行的运行结果不去关注,看到很明显的,InstantiationAwareBeanPostProcessor作用的是Bean实例化前后,即:

1、Bean构造出来之前调用postProcessBeforeInstantiation()方法

2、Bean构造出来之后调用postProcessAfterInstantiation()方法

不过通常来讲,我们不会直接实现InstantiationAwareBeanPostProcessor接口,而是会采用继承InstantiationAwareBeanPostProcessorAdapter这个抽象类的方式来使用。

后记

如果只会写个Bean,配置在xml文件里面,注入一下,那是最最基础的Spring开发者。一个中级、高级的Spring开发者,必然会对Spring中的多个扩展点有所了解,并利用这些扩展点更好地为项目服务,使得整个代码结构更加地优雅,并且可读性、可维护性更好。

抛砖引玉,本文只是简单地介绍一些常用的Spring Bean扩展接口以及它们的简单用法,更深入的或者它们一些合适的使用场景,还需要留待网友朋友们自己去探索。

原文出处: 五月的仓颉

from: http://www.importnew.com/22775.html

Spring8:一些常用的Spring Bean扩展接口相关推荐

  1. java 扩展接口_详解常用的Spring Bean扩展接口

    前言 Spring是一款非常强大的框架,可以说是几乎所有的企业级Java项目使用了Spring,而Bean又是Spring框架的核心. Spring框架运用了非常多的设计模式,从整体上看,它的设计严格 ...

  2. Spring - BeanDefinitionRegistryPostProcessor 扩展接口 动态注册bean

    文章目录 Pre org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor 接口的继承关系 BeanD ...

  3. Spring - InstantiationAwareBeanPostProcessor 扩展接口

    文章目录 Pre org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor InstantiationA ...

  4. Spring - BeanFactoryPostProcessor 扩展接口

    文章目录 Pre org.springframework.beans.factory.config.BeanFactoryPostProcessor 源码探究 1 是否实现BeanDefinition ...

  5. Spring - DisposableBean扩展接口

    文章目录 Pre org.springframework.beans.factory.DisposableBean 使用场景 源码解析 扩展示例 Pre Spring Boot - 扩展接口一览 or ...

  6. Spring - ApplicationContextInitializer 扩展接口

    文章目录 Pre org.springframework.context.ApplicationContextInitializer扩展点 扩展接口 扩展生效方式 方式一 : Spring SPI扩展 ...

  7. Spring Boot - 扩展接口一览

    文章目录 扩展接口 扩展接口

  8. SpringBoot2 | Spring IOC 流程中核心扩展接口的12个扩展点源码分析(十一)

    微信公众号:吉姆餐厅ak 学习更多源码知识,欢迎关注. SpringBoot2 | SpringBoot启动流程源码分析(一) SpringBoot2 | SpringBoot启动流程源码分析(二) ...

  9. 被各种注解搞晕了?那快来看看Spring Bean注解详解!

    前言 本篇博客中,我们将会讨论用于声明不同类型 Beans 的几种最常用的 Spring Bean 注解. 众所周知,Spring 容器中有许多配置 Bean 的方法,我们既可以通过 XML 配置,也 ...

最新文章

  1. 【专升本计算机】2021年甘肃省专升本计算机全真模拟试题(二)
  2. JPA字段长度 Mysql数据库
  3. android ListView ListSelector 不起作用(被覆盖)
  4. Python Pandas General functions(静态方法)
  5. [ANE for Android]Java接口部分引用第三方JAR的解决办法
  6. C语言基础教程之强制类型转换
  7. 12个强大的Web服务测试工具
  8. 通信业正面临一场巨变,要么滚蛋要么改变
  9. [IM002] [Microsoft][ODBC 驱动程序管理器] 未发现数据源名称并且未指定默认驱动程序...
  10. R语言机器学习中数据可视化的杀手锏
  11. 20170917软件工程师在线笔试之员工幸福感问题
  12. 深入解析 ext2 文件系统
  13. 30+简约和平铺的WordPress复古主题
  14. java webservice接口开发实例_Webservice 接口开发简单例子
  15. 中国占三分之一!CBinsights世界最新独角兽排名出炉
  16. javascript中map和filter的区别
  17. pci-e插槽gen2 x4 link什么意思
  18. IDEA中如何快速导包
  19. DLT645-2007 规约 电表 报文解析
  20. 【虚拟终端工具】SecureCRT工具连接虚拟机、rz/sz传输、中文乱码问题解决

热门文章

  1. Lesson 3.张量的广播和科学运算
  2. 金融反欺诈和金融构建信用评分或者金融预测特征抽取案例
  3. 完全图解RNN、RNN变体、Seq2Seq、Attention机制
  4. 信息检索与数据挖掘的常用加权技术。
  5. Learning to Rank 中Listwise关于ListNet算法讲解及实现
  6. Spring-使用外部属性文件01
  7. java接口示例_【基础篇】java-接口及其示例
  8. 学习笔记Kafka(二)—— Kafka安装配置(1)—— JDKZookeeper安装、Zookeeper 常用操作
  9. 爬虫学习笔记(二十四)—— pyspider框架
  10. java更新 位置_请求位置信息更新  |  Android 开发者  |  Android Developers