refresh()

AbstractApplicationContext#refresh()

该方法是线程安全的方法,在startupShutdownMonitor的锁同步块中。

prepareRefresh()

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
39
40
/**
* Prepare this context for refreshing, setting its startup date and
* active flag as well as performing any initialization of property sources.
*/
protected void prepareRefresh() {
// Switch to active.
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);

if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Refreshing " + this);
}
else {
logger.debug("Refreshing " + getDisplayName());
}
}

// Initialize any placeholder property sources in the context environment.
initPropertySources();

// Validate that all properties marked as required are resolvable:
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();

// Store pre-refresh ApplicationListeners...
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
// Reset local application listeners to pre-refresh state.
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}

// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<>();
}

obtainFreshBeanFactory()

This implementation performs an actual refresh of this context’s underlying bean factory, shutting down the previous bean factory (if any) and initializing a fresh bean factory for the next phase of the context’s lifecycle.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) { //如果存在beanfactory, 则关闭
destroyBeans();
closeBeanFactory();
}
try {
//为上下文生命周期的下个阶段初始化一个新的beanfactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
//指定ID
beanFactory.setSerializationId(getId());
//设置是否允许被覆盖,是否允许循环引用
customizeBeanFactory(beanFactory);
//从Xml、Annotation、Groovy中读取Bean信息并注册。
loadBeanDefinitions(beanFactory);
//set the refrences to this.beanFactory.
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}

prepareBeanFactory(beanFactory)

Prepare the bean facotry for use in this context.

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
39
40
41
42
43
44
45
46
47
48
/**
* Configure the factory's standard context characteristics,
* such as the context's ClassLoader and post-processors.
* @param beanFactory the BeanFactory to configure
*/
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);

// Register early post-processor for detecting inner beans as ApplicationListeners.
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}

// Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}

postProcessBeanFactory(beanFactory)

Allows post-processing of the bean factory in context subclasses.

Modify the application context’s internal bean factory after its standard initialization.
All bean definitions will have bean loaded, but no beans have been instantiated yet.
This alllows for registering special BeanPostProcessors etc in certain Applicationcontext implementations.

invokeBeanFactoryPostProcessors(beanFactory);

invoke factory processors registered as beans in the creation.

Instantiate and invoke all registered BeanFactoryPostProcessor beans,
respecting explicit order if given. Must be called before singleton instantiation.

引入冬季

Java标准资源管理

强大
|面向资源|文件系统、artifact(Jar、War、ear)、远程资源(HTTP/FTP)|
|API整合|java.lang.ClassLoader.getResource\ java.io.File / java.net.URL|
|资源定位|java.net.URL / java.net.URI|
|面向流存储|java.net.URLConnection|
|协议扩展|java.net.URLStreamHandler / java.net.URLStreamHandlerFactory|
扩展复杂

扩展协议

Spring资源接口

类型 接口
输入流 org.springframework.core.io.InputStreamSource
只读资源 org.springframework.core.io.Resource
可写资源 org.springframework.core.io.WritableResource
编码资源 org.springframework.core.io.EncodedResource
上下文资源 org.springframework.core.io.ContextResource

Spring InputStreamResource

Spring内建Resource实现

|Bean 定义|无|org.springframework.beans.factory.support.BeanDefinitionResource|
|字节码|无|org.springframework.core.io.ByteArrayResource|
|类路径|classpath:/|org.springframework.core.io.ClassPathResource|
|文件系统|file:/|org.springframework.core.io.FileSystemResource|
|URL|URL支持的协议|org.springframework.core.io.UrlResource|
|ServletContext|无|org.springframework.web.context.support.ServletContextResource|

Spring Resource 接口扩展
Spring 资源加载器

  • Resource 加载器
    • org.springframework.core.io.ResourceLoader
      • org.springframewor.core.io.DefaultResourceLoader
        • org.springframework.core.io.FileSystemResourceLoader
        • org.springframework.core.io.ClassRelativeResourceLoader
        • org.springframework.context.support.AbstractapplicationContext

Spring 通配路径资源加载器

  • 通配路径ResourceLoader
    • org.springframework.core.io.support.ResourcePatternResolver
      • org.springframework.core.io.support.PathMatchingResourcePatternResolver
  • 路径匹配起
    • org.springframework.util.PathMatcher
      • Ant模式匹配实现 - org.springframework.util.AntPathMatcher

Spring 通配路径资源扩展

依赖注入 Spring Resource

@Value(“classpath:/…”)
private Resource resource;

依赖注入 ResourceLoader

  • 实现 ResourceLoaderAware 回调
  • @Autowire 注入 ResourceLoader
  • 注入ApplicationContext 作为 ResourceLoader

Java 标准资源管理扩展

1
2
3
4
5
6
7
8
9
10
11
12
13
public class XURLConnection extends URLConnection{

private final UrlResource resource;

protected XURLConnection(URL url){
super(url);
this.resource = new ClassPathResource(url.getPath());
}

public InputStream getInputStream() throws IOException{
return resource.getInputStream();
}
}
1
2
3
4
5
public class Handler extends URLStreamHandler{
protected URLConnection openConnection(URL u) throws IOException{
return new XURLConnection(u);
}
}
1
2
3
URL url = new URL("x:///META-INF/default.properties");
InputStream is = url.openStream();
System.out.println(StreamUtils.copyString(is, Charset.forName("UTF-8")));
  • 实现URLStreamHandler, 添加 -Djava.protocal.handler.pkgs 启动参数,指向URLStreamHandler 实现类的包

  • 实现URLStreamHandlerFactory 并传递到URL之中

SpringBean 元信息

BeanDefinition Class Diagram

元信息的配置

  • 通过资源的方式配置,如: XML、 Properties、Groovy
  • 通过注解配置 : @Bean
  • 通过API配置 :BeanDefinitionBuilder / GenericBeanDefinition

元信息的读取

1) Get beanDefinitionRegistry for registry beanDefinitions.
2) Get ResourceLoader
3) Get ClassLoader.

  • 读取通过资源方式配置,如:XmlBeanDefinitionReader、PropertiesBeanDefinitionReader、GroovyBeanDefinitionReader
  • 读取注解配置的Bean:AnnotatedBeanDefinitionReader

BeanDefinitionReader Class Diagram

1
2
3
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(beanFactory);
reader.register(Main.class);

元信息的解析

BeanDefinitionParser

图片版本的看不太清,整理一份文字版本的层级关系,除BeanDefinitionParser是顶层抽象接口外,其余Parser都是类或者抽象类。

  • BeanDefinitionParser
    • SpringConfiguredBeanDefinitionParser
    • AnnotationDrivenCacheBeanDefinitionParser
    • ScriptingDefaultsParser
    • ComponentScanBeanDefinitionParser
    • AnnotationConfigBeanDefinitionParser
    • AspectJAutoProxyBeanDewfinitionParser
    • SpringConfiguredBeanDefinitionParser
    • ConfigBeanDefinitionParser
    • AnnotationDrivenBeanDefinitionParser
    • AbstractBeanDefinitionParser
      • MBeanExportBeanDefinitionParser
      • MBeanServiceBeanDefinitionParser
      • ScriptBeanDefinitionParser
      • AbstractSingleBeanDefinitionParser
        • ExecutorBeanDefinitionParser
        • SchedulerBeanDefinitionParser
        • SetBeanDefinitionParser
        • AbstractPropertyLoadingBeanDefinitionParser
        • LoadTimeWeaverBeanDefinitionParser
        • CacheAdviceParser
        • ListBeanDefinitionParser
        • ScheduledTasksBeanDefinitionParser
        • MapBeanDefinitionParser
        • PropertiesBeanDefinitionParser
        • PropertyPathBeanDefinitionParser
        • AbstractSimpleBeanDefinitionParser
          • ConstantBeanDefinitionParser
          • AbstractJndiLocatingBeanDefinitionParser
            • JndiLookupBeanDefinitionParser
            • LocalStatelessSessionBeanDefinitionParser
            • RemoteStatelessSessionBeanDefinitionParser

SpringBean 注册

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
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {

BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
removeManualSingletonName(beanName);
}
}
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}

if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}

Spring BeanDefinition 合并阶段

GenericBeanDefinition -> RootBeanDefinition

Spring Bean Class 加载阶段

BeanDefinition 中定义的Class名称加载具体的Class类。

ClassLoader 类加载
Java Security 安全控制
ConfigurableBeanFactory 临时 ClassLoader

Spring Bean 实例化
实例化前:
InstantiationAwareBeanProcessor.postProcessorBeforeInstantiation()
提前生成一些代理对象,替换掉默认的springIOC的实现内容。
实例化
传统实例化方式
+ 实例化策略 InstantiationStrategy

构造器依赖注入(根据类型来注入)

实例化后
InstantiationAwareBeanProcessor.postProcessorAfterInstantiation()

Spring Bean 属性赋值前阶段

Bean的属性值元信息: PropertyValues
构造器参数值:ConstructorValues

Bean属性赋值前回调
<= 5.0 InstantiationAwareBeanPostProcessor#postProcessorPropertyValues();
>= 5.1 InstantiationAwareBeanPostProcessor#postProcessorProperties();

Spring Bean Aware 接口回调阶段

Aware接口是一个标志接口,并没有提供任何实现。
BeanNameAware
BeanClassLoaderAware
BeanFactoryAware
EnvironmentAware
EmbeddedValueResolverAware
ApplicationEventPublisherAware
MessageSourceAware
ApplicationContextAware

Spring Bean 初始化

初始化前
BeanPostProcessor#postProcessorBeforeInitialization
初始化
@PostConstructor
AfterPropertiesSet
init-method
初始化后
BeanPostProcessor#postProcessAfterInitialization
初始化完成
SmartinitializingSingleton#afterSingletonsInstanted

AbstractAutowireCapableBeanFactory
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
39
40
41
42
43
44
45
46
47
/**
* Initialize the given bean instance, applying factory callbacks
* as well as init methods and bean post processors.
* <p>Called from {@link #createBean} for traditionally defined beans,
* and from {@link #initializeBean} for existing bean instances.
* @param beanName the bean name in the factory (for debugging purposes)
* @param bean the new bean instance we may need to initialize
* @param mbd the bean definition that the bean was created with
* (can also be {@code null}, if given an existing bean instance)
* @return the initialized bean instance (potentially wrapped)
* @see BeanNameAware
* @see BeanClassLoaderAware
* @see BeanFactoryAware
* @see #applyBeanPostProcessorsBeforeInitialization
* @see #invokeInitMethods
* @see #applyBeanPostProcessorsAfterInitialization
*/
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}

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

try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}

return wrappedBean;
}

Spring Bean 销毁
销毁前
DestructionAwareBeanPostProcessor#postProcessorBeforeDestruction
销毁
@PreDestroy
实现DisposableBean接口的destroy方法
自定义销毁方法
垃圾回收
关闭Spring 容器
执行GC
SpringBean 覆盖finalize()方法被回调

Spring Bean 作用域
单例模式
singleton Bean 作用域:在BeanFactory中唯一。
原型模式
prototype Bean 作用域:

servlet 引擎:
request Bean 作用域: 将Spring Bean 存储在Servlet Request上下文中
session Bean 作用域:将SpringBean存储在HttpSession中
application bean 作用域:将SpringBean存储在ServletContext中。
自定义Bean 作用域

Spring BeanFactory 类图

BeanFactory是访问Spring bean容器的根接口。提供了一些获取Bean的基础方法定义。

BeanFactory

ListableBeanFactory 和 ConfigurableBeanFactory 提供了一些更具体的特殊目标。

ListableBeanFactory继承了BeanFactory, 容器可以以列表的形式获取bean的相关信息,提供了获取多个beanName的基础方法。
ListableBeanFactory

ConfigurableBeanFactory 继承了 hierarchicalBeanFactory, 提供了IOC容器的可配置能力,几乎所有的BeanFactory都会实现这个接口。
ConfigurableBeanFactory

AutowireCapableBeanFactory 提供了自动装配Bean的能力。

AutowireCapableBeanFactory

依赖注入的模式和类型

  • 手动
    • Xml资源配置元信息
    • Java注解配置元信息
      • @Bean
      • @Autowired
    • API配置元信息
  • 自动
    • Autowiring
    • 类型
      • No : 默认值,未激活自动绑定,需要手动指定依赖注入
      • byName: 根据被注入属性的名称做为Bean名称进行依赖查找,并将对象设置到该属性
      • byType: 根据被注入属性的类型做为依赖类型进行查找,并将对象设置到该属性
      • constructor: 特殊的byType,用于构造器参数

xml 资源配置元信息

1
2
3
<bean id="" name="" class="">
<property name="name" ref="nameObj"/>
</bean>
依赖注入类型 示例
set <property name=”user” ref=”userBean”/>
构造器 <constructor-arg name=”user” ref=”userBean”/>
字段注入 @Autowired User user;
方法注入 @Autowired public void user(User user){}
回调注入 class MyBean implements BeanFactoryAware{}

依赖注入选择

基础类型注入
集合类型注入
限定注入
延迟依赖注入
依赖处理过程
@Autowired 注入原理
JSR-330@inject注入原理
Java通用注解注入原理
自定义依赖注解

自动绑定
模式
限制和不足

题目精选

依赖查找

历史

单一类型依赖查找

JNDI - javax.naming.Context#lookup*(javax.naming.Name);
JavaBeans - java.beans.beancontext.BeanContext

  • BeanFactory:
    • 根据bean名称查找
      • getBean(String);
      • getBean(String,Object…) //覆盖默认参数
    • 根据Bean类型查找
      • bean实时查找
        • getBean(Class)
        • getBean(Class,Object…)//覆盖默认参数
      • bean延时查找
        • getBeanProvider(Class);
        • getBeanProvider(String,Class);
    • 根据Bean名称和类型查找
      • getBean(String,Class);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* 通过 {@link org.springframework.beans.factory.ObjectProvider} 进行依赖查找
*/
public class ObjectProviderDemo {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(ObjectProviderDemo.class);
applicationContext.refresh();
lookupByObjectProvider(applicationContext);
applicationContext.close();
}

@Bean
public String helloWorld() {
return "Hello World";
}
private static void lookupByObjectProvider(AnnotationConfigApplicationContext applicationContext) {
ObjectProvider<String> objectProvider = applicationContext.getBeanProvider(String.class);
System.out.println(objectProvider.getObject());
}
}

集合类型依赖查找

java.beans.beancontext.BeanContext

ListableBeanFactory

是针对某个类型去查找一个集合列表。
一种是查询bean的名称, 一种是查询bean的实例。
一般情况下应该使用bean的名称来判断当前bean是否存在,或者进一步判断BeanDefinition是否存在。
而查询bean实例会提早初始化bean实例,造成初始化不完整。

  • 根据Bean类型查找
    • 获取同类型Bean名称列表
      • getBeanNamesForType(Class)
      • getBeanNamesForType(ResolvableType)
    • 获取痛类型Bean实例列表
      • getBeansOfType(Class)以及重载方法
  • 根据注解类型查找
    • 获取标注类型Bean 名称列表
      • getBeanNamesForAnnotation(Class<? extends Annotation>);
    • 获取标注类型Bean实例列表
      • getBeansWithAnnotation(Class<? extends Annotation>);
    • 获取指定名称+标注类型实例
      • findAnnotationOnBean(String,Class<? extends Annotation>);

层次性依赖查找

java.beans.beancontext.BeanContext

HierachicalBeanFactory

  • 双亲 BeanFactory: getParentBeanFactory();
    • 层次查找
    • 根据Bean名称查找
      • 基于containsLocalBean方法实现
    • 根据Bean类型查找实例列表
      • 单一类型:BeanFactoryUtils#beanOfType
      • 集合类型:BeanFactoryUtils#beansOfTypeIncludingAncestors
    • 根据Java注解查找名称列表
      • BeanFactoryUtils#beanNamesForTypeIncludingAncestors
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
39
40
41
42
43
44
45
46
47
48
49
50
51
public class HierarchicalDependencyLookupDemo {


public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();

ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory();

HierarchicalBeanFactory parentBeanFactory = createParentBeanFactory();

beanFactory.setParentBeanFactory(parentBeanFactory);

displayContainsLocalBean(beanFactory, "user"); //false
displayContainsLocalBean(parentBeanFactory, "user"); //true

displayContainsBean(beanFactory, "user"); //true
displayContainsBean(parentBeanFactory,"user");//true

applicationContext.refresh();
applicationContext.close();
}


private static void displayContainsBean(HierarchicalBeanFactory beanFactory, String beanName) {
System.out.printf("当前 BeanFactory [%s] 是否包含 bean[name:%s] %s\n", beanFactory, beanName, containsBean(beanFactory,beanName));

}

private static boolean containsBean(HierarchicalBeanFactory beanFactory, String beanName) {
BeanFactory parentBeanFactory = beanFactory.getParentBeanFactory();
if (parentBeanFactory instanceof HierarchicalBeanFactory) {
HierarchicalBeanFactory parentHierarchicalBeanFactory = HierarchicalBeanFactory.class.cast(parentBeanFactory);
if (containsBean(parentHierarchicalBeanFactory, beanName)) {
return true;
}
}
return beanFactory.containsLocalBean(beanName);
}

private static void displayContainsLocalBean(HierarchicalBeanFactory parentBeanFactory, String user) {
System.out.printf("当前 BeanFactory [%s] 是否包含 Local bean[name:%s] %s\n", parentBeanFactory, user, parentBeanFactory.containsLocalBean(user));
}

private static HierarchicalBeanFactory createParentBeanFactory() {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
String location = "classpath:applicationContext-lookup.xml";
reader.loadBeanDefinitions(location);
return beanFactory;
}
}

延迟依赖查找

  • Bean延迟依赖查找接口
    • org.springframework.beans.factory.ObjectFactory#getObject();
    • org.springframework.beans.factory.ObjectProvider
      • Spring5对于Java8的特性扩展
      • 函数式接口
        • getIfAvailable(Supplier)
        • ifAvailable(Consumer)
      • Stream扩展 - stream()
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
39
40
41
42
43
44
45
46
47
48
49
/**
* 通过 {@link org.springframework.beans.factory.ObjectProvider} 进行依赖查找
*/
public class ObjectProviderDemo {


public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(ObjectProviderDemo.class);
applicationContext.refresh();

lookupByObjectProvider(applicationContext);
lookupIfAvailable(applicationContext);
lookupByStream(applicationContext);
applicationContext.close();
}

private static void lookupByStream(AnnotationConfigApplicationContext applicationContext) {
ObjectProvider<String> objectProvider = applicationContext.getBeanProvider(String.class);
// Iterator<String> iterator = objectProvider.iterator();
// while(iterator.hasNext()){
// System.out.println(iterator.next());
// }
objectProvider.stream().forEach(System.out::println);
}

private static void lookupIfAvailable(AnnotationConfigApplicationContext applicationContext) {
ObjectProvider<User> userObjectProvider = applicationContext.getBeanProvider(User.class);
User user = userObjectProvider.getIfAvailable(User::new);
System.out.println(user);

}

@Bean
@Primary
public String helloWorld() {
return "Hello World";
}

@Bean
public String message(){
return "message";
}

private static void lookupByObjectProvider(AnnotationConfigApplicationContext applicationContext) {
ObjectProvider<String> objectProvider = applicationContext.getBeanProvider(String.class);
System.out.println(objectProvider.getObject());
}
}

安全依赖查找

依赖查找安全性对比

依赖查找类型 代表实现 是否安全
单一类型查找 BeanFactory#getBean
ObjectFactory#getObject
ObjectProvider#getIfAvailable
集合类型查找 ListableBeanFactory#getBeansOfType
ObjectProvider.stream
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import com.github.springframework.models.User;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class TypeSafetyDependencyLookupDemo {

public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(TypeSafetyDependencyLookupDemo.class);
applicationContext.refresh();

displayBeanFactoryGetBean(applicationContext);
displayObjectFactoryGetObject(applicationContext);
displayObjectProviderIfAvailable(applicationContext);

displayListableBeanFactoryGetBeansOfType(applicationContext);

displayObjectProviderStreamOps(applicationContext);
applicationContext.close();
}

public static void displayObjectProviderStreamOps(AnnotationConfigApplicationContext beanFactory){
ObjectProvider<User> userObjectFactory = beanFactory.getBeanProvider(User.class);
printException("displayObjectProviderStreamOps", ()->userObjectFactory.forEach(System.out::println));
}

public static void displayListableBeanFactoryGetBeansOfType(ListableBeanFactory beanFactory){
printException("displayListableBeanFactoryGetBeansOfType", ()->beanFactory.getBeansOfType(User.class));
}

public static void displayObjectProviderIfAvailable(BeanFactory beanFactory){
ObjectProvider<User> userObjectFactory = beanFactory.getBeanProvider(User.class);
printException("displayObjectProviderIfAvailable", ()->userObjectFactory.getIfAvailable());
}

public static void displayObjectFactoryGetObject(BeanFactory beanFactory){
ObjectProvider<User> userObjectFactory = beanFactory.getBeanProvider(User.class);
printException("displayObjectFactoryGetObject", ()->userObjectFactory.getObject());
}

public static void displayBeanFactoryGetBean(BeanFactory beanFactory){
printException("displayBeanFactoryGetBean",()->beanFactory.getBean(User.class));
}

public static void printException(String source, Runnable run){
System.out.println("Source From : " + source);
System.out.println("======================================");
try{
run.run();
}catch (BeansException e){
e.printStackTrace();
}
}
}

内建可查找的依赖

  • AbstractApplicationContext 内建可查找依赖
Bean名称 Bean实例 使用场景
environment Environment对象 外部化配置以及Profiles
systemProperties java.util.Proerties对象 Java系统属性
systemEnvironment java.util.Map对象 操作系统环境变量
messageSource MessageSource对象 国际化文案
lifecycleProcessor LifecycleProcessor对象 LifecycleBean处理器
applicationEventMulticaster ApplicationEventMulticaster对象 Spring事件广播器
  • 注解驱动Spring上下文内建可查找的依赖

AnnotationConfigUtils.

Bean名称 Bean实例 使用场景
org.springframework.context.annotation.internalConfigurationAnnotationProcessor ConfigurationClassPostProcessor对象 处理Spring配置类
org.springframework.context.annotation.internalAutowiredAnnotationProcessor AutowireAnnotationBeanPostProcessor对象 处理@Autowired以及@Value注解
org.springframework.context.annotation.internalCommonAnnotatinProcessor CommonAnnotationBeanPostProcessor对象 条件激活处理JSR-250注解,如@PostConstruct
org.springframework.context.event.internalEventListenerProcessor EventListenerMethodProcessor对象 处理@EventListener的Spring事件监听方法

依赖查找中的异常

  • NoSuchBeanDefinitionException
  • NoUniqueBeanDefinitionException
  • BeanInstantiationException
  • BeanCreationException
  • BeanDefinitionStoreException

常见题目

  • ObjectFactory 和 BeanFactory 的区别
  • BeanFactory.getBean 的线程安全性

BeanDefinition

A BeanDefinition describes a bean instance, which has property values,
Constructor arguments values, and further information supplied by concrete implementations.
This is just a minimal interface: The main intention is to allow a BeanFactoryPostProcessor to introspect and modify property values and other bean metadata.

BeanDefinition 类图

BeanDefinition: 顶级父接口,继承了BeanMetadataElement和AttributeAccessor.

AbstractBeanDefinition:是GenericBeanDefinition、RootBeanDefinition、ChildBeanDefinition 的通用属性的完整实现。
GenericBeanDefinition: 标准的bean定义目的的一站式服务类.
RootBeanDefinition: 根Bean定义,代表合并的BeanDefinition。
ChildBeanDefinition: 有parent的BeanDefinition

BeanDefinition是SpringFramework中定义的配置元信息接口,包含了:

  • Bean 的类名
  • Bean 的行为配置元素,如作用域、自动绑定模式、生命周期回调等
  • 其他Bean引用,(Collaborators、Dependends)
  • 配置设置(Bean的Properties)

BeanDefinition 元信息

属性 说明
Class Bean的全限类名,必须是具体类
Name Bean的名称或者🆔
Scope Bean的作用域,singleton、prototype
Constructor arguments Bean的构造器参数 for DI
Properties Bean的属性设置 for DI
Autowiring Mode Bean的自动绑定模式:ByName 、 byType
Lazy Initialization Mode Bean 延迟初始化模式
initialzation method Bean初始化回调方法名称
destruction method Bean 销毁回调方法名称

BeanDefinition 构建

  • 通过BeanDefinitionBuilder构建Beandefinition
1
2
3
4
5
6
7
        //bean definition builder.
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User.class);

beanDefinitionBuilder.addPropertyValue("id",1L);
beanDefinitionBuilder.addPropertyValue("name","lisi");

BeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
  • 通过GenericBeanDefinition 构建
1
2
3
4
5
6
7
8
9
10
GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition();
genericBeanDefinition.setBeanClass(User.class);

MutablePropertyValues propertyValues = new MutablePropertyValues();
// propertyValues.addPropertyValue("id",2L);
// propertyValues.addPropertyValue("name","zhaowu");

propertyValues.add("id",2L)
.add("name","zhaowu");
genericBeanDefinition.setPropertyValues(propertyValues);

SpringBean 命名

每个Bean拥有一个或者多个标识符,这些标识符在Bean所在的容器必须是唯一的。
通常,一个Bean仅有一个标识符,可以考虑使用别名来扩充。

在基于XML的配置元信息中,可以使用id或者name属性来规定Bean的标识符。通常Bean的标识符由字母组成,允许出现特殊字符。可以在Bean的name属性使用逗号“,”或者“;”或者空格来间隔名称做为别名。

Bean的id或者name属性如果为空,容器会为Bean自动生成一个唯一的名称。

BeanNameGenerator

BeanNameGenerator 类图

DefaultBeanNameGenerator

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
39
40
41
42
/**
* Generate a bean name for the given bean definition, unique within the
* given bean factory.
* @param definition the bean definition to generate a bean name for
* @param registry the bean factory that the definition is going to be
* registered with (to check for existing bean names)
* @param isInnerBean whether the given bean definition will be registered
* as inner bean or as top-level bean (allowing for special name generation
* for inner beans versus top-level beans)
* @return the generated bean name
* @throws BeanDefinitionStoreException if no unique name can be generated
* for the given bean definition
*/
public static String generateBeanName(
BeanDefinition definition, BeanDefinitionRegistry registry, boolean isInnerBean)
throws BeanDefinitionStoreException {

String generatedBeanName = definition.getBeanClassName();
if (generatedBeanName == null) {
if (definition.getParentName() != null) {
generatedBeanName = definition.getParentName() + "$child";
}
else if (definition.getFactoryBeanName() != null) {
generatedBeanName = definition.getFactoryBeanName() + "$created";
}
}
if (!StringUtils.hasText(generatedBeanName)) {
throw new BeanDefinitionStoreException("Unnamed bean definition specifies neither " +
"'class' nor 'parent' nor 'factory-bean' - can't generate bean name");
}

String id = generatedBeanName;
if (isInnerBean) {
// Inner bean: generate identity hashcode suffix.
id = generatedBeanName + GENERATED_BEAN_NAME_SEPARATOR + ObjectUtils.getIdentityHexString(definition);
}
else {
// Top-level bean: use plain class name with unique suffix if necessary.
return uniqueBeanName(generatedBeanName, registry);
}
return id;
}

由代码可以看出, 首先获取BeanClassName, BeanClassName 为空时,获取ParentName,ParentName为空时获取FactoryBeanName, 当三者都为空的时候名称是无法创建的。 三者不为空时生成的名称前缀为:
BeanClassName
ParentName$child
FactoryBeanName$created

在生成名字时,如果是内部类, 则生成名字为前缀+#+当前beanDefinition的hashCode, 如下:
BeanClassName#hashCode
ParentName$child#hashCode
FactoryBeanName$created#hashCode

如果不是内部类, 则调用uniqueBeanName生成唯一的BeanName,格式为 + “#” + 序号。

BeanClassName#1
ParentName$child#1
FactoryBeanName$created#1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* Turn the given bean name into a unique bean name for the given bean factory,
* appending a unique counter as suffix if necessary.
* @param beanName the original bean name
* @param registry the bean factory that the definition is going to be
* registered with (to check for existing bean names)
* @return the unique bean name to use
* @since 5.1
*/
public static String uniqueBeanName(String beanName, BeanDefinitionRegistry registry) {
String id = beanName;
int counter = -1;

// Increase counter until the id is unique.
while (counter == -1 || registry.containsBeanDefinition(id)) {
counter++;
id = beanName + GENERATED_BEAN_NAME_SEPARATOR + counter;
}
return id;
}

AnnotationBeanNameGeneritor

先判断是否为AnnotatedBeanDefinition, 优先按照AnnotationBeanDefinition配置的Value获取,如果没有配置,则按照缺省的方式来生成beanName(如果是mypackage.MyJdbcDao 则生成 myJdbcDao)。

1
2
3
4
5
6
7
8
9
10
11
12
@Override
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
if (definition instanceof AnnotatedBeanDefinition) {
String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition);
if (StringUtils.hasText(beanName)) {
// Explicit bean name found.
return beanName;
}
}
// Fallback: generate a unique default bean name.
return buildDefaultBeanName(definition, registry);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* Derive a default bean name from the given bean definition.
* <p>The default implementation simply builds a decapitalized version
* of the short class name: e.g. "mypackage.MyJdbcDao" -> "myJdbcDao".
* <p>Note that inner classes will thus have names of the form
* "outerClassName.InnerClassName", which because of the period in the
* name may be an issue if you are autowiring by name.
* @param definition the bean definition to build a bean name for
* @return the default bean name (never {@code null})
*/
protected String buildDefaultBeanName(BeanDefinition definition) {
String beanClassName = definition.getBeanClassName();
Assert.state(beanClassName != null, "No bean class name set");
String shortClassName = ClassUtils.getShortName(beanClassName);
return Introspector.decapitalize(shortClassName);
}

BeanDefinition 配置

Xml

1
2
3
4
5
6
7
8
9
10
11
12
<bean id="user" class="com.github.springframework.models.User" primary="true">
<property name="id" value="1"/>
<property name="name" value="zhangsan"/>
</bean>

<bean id="superUser" class="com.github.springframework.models.SuperUser" parent="user" >
<property name="addr" value="上海"/>
</bean>

<bean id="objectFactory" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
<property name="targetBeanName" value="user"/>
</bean>

Java注解 @Bean

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
public class AnnotationBeanDefinitionDemo {


public static void main(String[] args) {

//create factory bean
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();

//register config class.
applicationContext.register(Config.class);

//refresh
applicationContext.refresh();

//getUser
System.out.println(applicationContext.getBean(User.class));
}



static class Config{
@Bean
public User user(){
User user = new User();
user.setId(1L);
user.setName("Ann: zhangsan");
return user;
}
}
}

Java注解 @Component

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
public class AnnotationBeanDefinitionDemo {
public static void main(String[] args) {
//create factory bean
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();

//register config class.
applicationContext.register(Config.class);

//refresh
applicationContext.refresh();

//
System.out.println(applicationContext.getBean(Config.class));
}
@Component
static class Config{
@Bean
public User user(){
User user = new User();
user.setId(1L);
user.setName("Ann: zhangsan");
return user;
}
}
}

BeanDefinition注册到容器

BeanDefinitionRegistry 提供了 BeanDefinition 的注册、删除,获取,判断是否存在等功能。

BeanDefinitionRegistry 类图1

BeanDefinitionRegistry 类图2

1
2
3
4
5
6
7
8
9
10
static void beanDefinitionRegistry(BeanDefinitionRegistry registry, String name) {
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User.class);
beanDefinitionBuilder.addPropertyValue("id", 1L)
.addPropertyValue("name", "Reg: zhangsan");
if (StringUtils.hasText(name)) {
registry.registerBeanDefinition(name, beanDefinitionBuilder.getBeanDefinition());
} else {
BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinitionBuilder.getBeanDefinition(),registry);
}
}

由于AnnotatinoConfigApplicationContext 是 BeanDefinitionRegistry的间接子类。

1
2
3
4
5
6
7
8
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(Config.class);
beanDefinitionRegistry(applicationContext,"REG:ZhangSan:Name");
beanDefinitionRegistry(applicationContext,null);
applicationContext.refresh();
System.out.println(applicationContext.getBeansOfType(Config.class));
System.out.println(applicationContext.getBeansOfType(User.class));
System.out.println(applicationContext.getBeansOfType(AnnotationApplicationContextDemo.class));

Bean 实例化

常规:

  • 通过构造器(配置元信息:XML、Java注解、JavaAPI)

  • 静态工厂方法(配置元信息:XML、JavaAPI)

1
2
3
4
5
6
7
8
9
10
public class User2 {

private Long id;

private String name;

public static User2 getInstance(){
return new User2();
}
}
1
<bean id="user-by-static-method" class="com.github.spring.beans.User2"  factory-method="getInstance"></bean>
1
2
3
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/META-INF/bean-creation-context.xml");

User2 user = applicationContext.getBean("user-by-static-method", User2.class);
  • Bean工厂方法(配置元信息:XML、JavaAPI)
1
2
3
4
5
6
7
8
public interface UserFactory {
default User2 createuser() {
return new User2();
}
}

public class DefaultUserFactory implements UserFactory {
}
1
2
<bean id="userFactory" class="com.github.spring.factory.DefaultUserFactory"/>
<bean id="user-by-instance-method" factory-bean="userFactory" factory-method="createuser"/>
1
2
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/META-INF/bean-creation-context.xml");
User2 user3 = applicationContext.getBean("user-by-instance-method", User2.class);
  • FactoryBean(XML、Java注解、JavaAPI)
1
2
3
4
5
6
7
8
9
10
11
12
public class UserFactoryBean implements FactoryBean<User2> {

@Override
public User2 getObject() throws Exception {
return User2.getInstance();
}

@Override
public Class<?> getObjectType() {
return User2.class;
}
}
1
<bean id="user-by-factory-bean" class="com.github.spring.factory.UserFactoryBean"/>
1
2
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/META-INF/bean-creation-context.xml");
User2 user2 = applicationContext.getBean("user-by-factory-method", User2.class);

特殊方式:

  • ServiceLoaderFactoryBean

Java ServiceLoader: 会在classpath:/META-INF/services下加载接口配置文件:

文件名名称为全限定接口名称,内容为全限定实现类

services 配置文件

1
com.github.spring.factory.DefaultUserFactory
1
2
3
4
5
6
7
8
9
10
11
12
public static void demoServiceLoader() {
ServiceLoader<UserFactory> serviceLoader = ServiceLoader.load(UserFactory.class, Thread.currentThread().getContextClassLoader());
displayServiceLoad(serviceLoader);
}

public static void displayServiceLoad(ServiceLoader<UserFactory> serviceLoader) {
Iterator<UserFactory> iterator = serviceLoader.iterator();
while (iterator.hasNext()) {
UserFactory userFactory = iterator.next();
System.out.println(userFactory.createuser());
}
}

ServiceLoaderFactoryBean的实现

1
2
3
<bean id="userFactoryServiceLoader" class="org.springframework.beans.factory.serviceloader.ServiceLoaderFactoryBean">
<property name="serviceType" value="com.github.spring.factory.UserFactory"/>
</bean>
1
2
3
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/META-INF/sp-bean-creation-context.xml");
ServiceLoader<UserFactory> serviceLoader = applicationContext.getBean("userFactoryServiceLoader", ServiceLoader.class);
displayServiceLoad(serviceLoader);
  • AutowireCapableBeanFactory#createBean(java.lang.Class,int, boolean);
1
2
3
AutowireCapableBeanFactory beanFactory = applicationContext.getAutowireCapableBeanFactory();
UserFactory userFactory = beanFactory.createBean(DefaultUserFactory.class);
System.out.println(userFactory.createuser());
  • BeanDefinitionRegistry#registerBeanDefinition(String,BeanDefinition);

Bean的初始化

  • @PostConstructor

  • InitializingBean 的 afterPropertiesSet

  • Bean的initMethod
    @Bean(initMethod=””)

    AbstractBeanDefinition.setInitMethodName("");
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class DefaultUserFactory implements UserFactory, InitializingBean {

public DefaultUserFactory() {
System.out.println("DefaultUserFactory Constructor Called.");
}

@PostConstruct
public void init(){
System.out.println("DefaultUserFactory PostConstructor Called.");
}

public void initUserFactory(){
System.out.println("DefaultUserFactory initUserFactory Called.");
}

@Override
public void afterPropertiesSet() throws Exception {
System.out.println("DefaultUserFactory afterPropertiesSet called.");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Configuration
public class BeanInitializationDemo {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(BeanInitializationDemo.class);
applicationContext.refresh();
UserFactory userFactory = applicationContext.getBean(UserFactory.class)
System.out.println(userFactory.createuser());
applicationContext.close();
}

@Bean(initMethod = "initUserFactory")
public DefaultUserFactory userFactory(){
return new DefaultUserFactory();
}
}

延迟初始化

  • xml:
  • annotation: @Lazy

对于延迟初始化,是在applicationContext初始化之后进行初始化。
非延迟初始化,是在applicationContext初始化之前进行初始化。

Bean 的销毁

  • @PreDestroy
  • 实现DisposableBean接口的destoy()方法
  • Bean的 destroy方法 @Bean(destroy="") AbstractBeanDefinition.setDestroyMethodName("");

  • 如何注册一个Spring Bean

可以通过BeanDefinition和外部单体对象来注册。

1
2
3
4
5
UserFactory userFactory = new DefaultUserFactory();
ConfiguableListableBeanFactory factory = applicationContext.getBeanFactory();
factory.registerSingleton("userFactory", userFactory);

UserFactory userFactory = applicationContext.getBean("UserFactory",UserFactory.class);
  • Spring BeanDefinition 是什么?

  • Spring 容器是如何注册Bean的?

IOC 简史

  • 1983年,Richard E.Sweet 在<>提出好莱坞原则(“不要打电话给我,我会打电话给你”)。
  • 1988年,Rolph E.Johnson 和Brian Foote在《Designing Reusable Classes》中提出控制反转。
  • 1996年,Michael Mattson在《Object-Oriented Frameworks, A survey of methodological issues》将控制反转命名为好莱坞原则。
  • 2004,Martin Fowler在《Inversion Of Control Containers and the Dependency Injection pattern》提出自己对和IOC和DI的理解
  • 2005年,Martin Folower在《Inversion Of Control》中对IOC进一步说明。
  • Martin 大爷关于IOC的说明

IOC 的实现策略

WIKI:

In object-oriented programming, there are several basic techniques to implement inversion of control. there are:

  • Using a service locator pattern
  • Using dependency injection
    • constructor injection
    • parameter injection
    • setter injection
    • interface injection
  • Using a contextualized lookup.
  • Using template method design pattern
  • Using Strategy design pattern.

EXPERT ONE-ON-ONE J2EE DEVELOPMENT without EJB提到的策略: