22 KiB
Java and Spring
来源:原 mongodb 集合
t_blog· 整理日期:2026-08-25 分类 ID:00000000000002· 排序:1 · 文章数:14
目录
- Springboot AbstractApplicationContext
- Map Set List
- Java8 AQS
- Java8 Stream
- Spring superinterface
- Springboot DefaultSingletonBeanRegistry
- Springboot SpringApplication
- Springboot AbstractBeanFactory
- Springboot AbstractAutowireCapableBeanFactory
- Springboot AbstractBeanDefinition
- Springboot ConfigurationClassPostProcessor
- Spring ASM
- PostProcessorRegistrationDelegate
- Spring Aop
1. Springboot AbstractApplicationContext
bid: 00000000000003
AbstractApplicationContext
AbstractApplicationContext 是 SpringBoot的 核心应用上下文父类。
x.1 properties
beanFactoryPostProcessors
environment
x.2 methods
refresh
refresh 是 Springboot启动中核心方法。
- prepareRefresh
- obtainFreshBeanFactory
- prepareBeanFactory
- postProcessBeanFactory
- invokeBeanFactoryPostProcessors
- registerBeanPostProcessors
- onRefresh
- finishBeanFactoryInitialization
- finishRefresh
2. Map Set List
bid: 2022051816085000000000000006
1. Summary
我们在开发过程在,最常见的三种数据存储结构就是 Map Set 和List了
这三种结构最明显的特征就是Map 是键值,Set是对象存储唯一,List是有序数组
Map<K, V>
键值存储,主键不允许重复
添加元素 使用put方法,如果key重复,则value被覆盖
Set
对象存储,对象不允许重复
/**
* if this set did not already contain the specified element will return {@code true}
* f this set already contains the element, the call leaves the set
* unchanged and returns {@code false}
*/
public boolean add(E e)
List
list是由数组构成的,这就意味着,list是有顺序的,因为数组在内存中是一段连续的内存。
3. Java8 AQS
bid: 2022052314143400000000000014
AQ
4. Java8 Stream
bid: 2022060810550500000000000022
S
5. Spring superinterface
bid: 2022120915183100000000000001
summary
1. Aware(感知)
Spring Ioc 是解耦行为,我们的业务代码其实是没有感知或者意识到spring框架的存在。如果我们需要使用spring Ioc中的资源时候,我们就需要有意识的去获取这个资源,而Aware 就是这样的存在。
@Service
public class AppContextAware implements ApplicationContextAware {
ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext=applicationContext;
}
public void hello(){
//user为容器中存在的bean
User user = applicationContext.getBean("user", User.class);
System.out.println(user);
//获取容器的环境、User.name为设置好的属性
Environment environment = applicationContext.getEnvironment();
String property = environment.getProperty("User.name");
System.out.println(" 属性:"+property);
}
}
一些常用的Aware interface
BeanNameAware
ApplicationContextAware
ResourceLoaderAware
EnvironmentAware
2. BeanFactory
BeanFactory 提供了获取bean和判断bean的方法,包括
getBean(String beanName)
getBean(String beanName, Class<T> requiredType)
getBean(Class<T> requiredType)
containsBean(String name)
isSingleton(String name)
isPrototype(String name)
sTypeMatch(String name)
getType(String name)
String[] getAliases(String name);
3. BeanPostProcessor
4. BeanFactoryPostProcessor
5. ApplicationContext
6. InitializingBean
6. Springboot DefaultSingletonBeanRegistry
bid: 2022121513519200000000000002
DefaultSingletonBeanRegistry
DefaultSingletonBeanRegistry 是Springboot bean 自动装配的核心实现类。
顾名思义,是默认的单例bean 注册器。
x.1 properties
dependentBeanMap
存放(依赖对象key -> 被依赖Set)的 ConcurrentHashMap
private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);
dependenciesForBeanMap
存放(被依赖对象key -> 依赖Set)的 ConcurrentHashMap
private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);
x.2 methods
registerDependentBean
我们知道Spring DI 依赖注入,此方法就是依赖注入的核心组成。注意,这段逻辑是加锁的,即存在并行处理逻辑。 Springboot 在 AbstractApplicationContext 进行 refresh 操作时候,在最后一步会实例化bean,参照AbstractApplicationContext.finishBeanFactoryInitialization 方法,此方法的流程我们会在xxx讲解。源码如下
/**
* Register a dependent bean for the given bean。
*/
public void registerDependentBean(String beanName, String dependentBeanName) {
String canonicalName = canonicalName(beanName);
synchronized (this.dependentBeanMap) {
Set<String> dependentBeans =
this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
if (!dependentBeans.add(dependentBeanName)) {
return;
}
}
synchronized (this.dependenciesForBeanMap) {
Set<String> dependenciesForBean =
this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
dependenciesForBean.add(canonicalName);
}
}
DI 在此处的实现逻辑可以通过下面例子来通俗说明:
① A对象 依赖 B对象
② A对象 依赖 C对象
③ D对象 依赖 B对象
所以 必须要提前先把 B 对象和 C对象进行实例化后,才能 创建A对象和 D对象。
我们从RootBeanDefinition中获取 dependsOn的数组,遍历调用registerDependentBean方法
参数beanName是依赖对象,即 B 或者 C,参数dependentBeanName是被依赖对象A
- 传入参数是 (B,A) 时,为 B 创建一个 LinkedHashSet,并在该Set中存放A, 并把 B -> Set的映射关系放入dependentBeanMap中。
紧接着 为 A 创建一个 LinkedHashSet, 并在该Set中存放B,并把 A -> Set的映射关系放入dependenciesForBeanMap中。 - 传入参数是 (C, A) 时,为 C 创建一个 LinkedHashSet,并在该Set中存放A, 并把 C -> Set的映射关系放入dependentBeanMap中。
因为 dependenciesForBeanMap 已经存在了 A -> Set这个映射,我们只需将 C 也存入这个Set就可以。 - 传入参数是 (B, D) 时,因为 dependentBeanMap 已经存在了 B -> Set这个映射,我们只需将 D 也存入这个Set就可以。 紧接着 为 D 创建一个 LinkedHashSet, 并在该Set中存放B,并把 D -> Set的映射关系放入dependenciesForBeanMap中。
注意 依赖和被依赖总是成对出现的,dependentBeans.add(dependentBeanName) 返回 false,视为添加失败,即视为已经存在,根据 依赖和被依赖总是成对出现的,所以后面dependenciesForBean.add(canonicalName) 这部分就没必要执行了,因为执行了也没有意义,所以直接 return了。毕竟dependenciesForBean中已经存在了canonicalName。
7. Springboot SpringApplication
bid: 2022121513597200000000000003
SpringApplication
x.1 properties
sources
environment
webApplicationType
x.2 methods
run
- 创建 DefaultBootstrapContext
- 获取 SpringApplicationRunListeners
- 转换 ApplicationArguments 将commandLine args
- 装备环境 ConfigurableEnvironment
- 配置忽略bean情报 configureIgnoreBeanInfo
- 创建 ApplicationContext
- 准备 ApplicationContext prepareContext 设置上下文环境,加载source
- 刷新 ApplicationContext
- 刷新后处理
8. Springboot AbstractBeanFactory
bid: 2022121515315000000000000004
AbstractBeanFactory
x.2 methods
doGetBean
AbstractBeanFactory 的核心方法 doGetBean,doGetBean方法是由getBean调用的,如果有dependsOn存在,就会将注册依赖, 然调用getBean(dep),从而形成了递归操作。
当不存dependsOn的时候mbd.isSingleton 时候,就会调用 getSingleton方法,子类会回调createBean(beanName, mbd, args)方法,去创建bean。
源码
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType) {
String beanName = transformedBeanName(name);
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance.
if (mbd.isSingleton()) {
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);
}
}
9. Springboot AbstractAutowireCapableBeanFactory
bid: 2022121523309700000000000005
AbstractAutowireCapableBeanFactory
父类是AbstractBeanFactory,实现了AutowireCapableBeanFactory 的方法,其中最主要的还是createBean方法。 源码
/**
* Central method of this class: creates a bean instance,
* populates the bean instance, applies post-processors, etc.
* @see #doCreateBean
*/
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
10. Springboot AbstractBeanDefinition
bid: 2022121523361800000000000006
AbstractBeanDefinition
AbstractBeanDefinition 定义了 一个bean的各种描述。
x.1
String[] dependsOn
Resource resource
11. Springboot ConfigurationClassPostProcessor
bid: 2022121612282000000000000009
ConfigurationClassPostProcessor
这一节主要讲的是ConfigurationClassPostProcessor和他的一些生态。 他的生态有
-
ConfigurationClassParser 真正的处理者。
-
ComponentScanAnnotationParser 扫描classpath,把beanName加入到registry的beanDefinitionMap中。
-
doProcessConfigurationClass 是该 postProcessor最核心的处理方法
/** * Apply processing and build a complete {@link ConfigurationClass} by reading the * annotations, members and methods from the source class. This method can be called * multiple times as relevant sources are discovered. * @param configClass the configuration class being build * @param sourceClass a source class * @return the superclass, or {@code null} if none found or previously processed */ @Nullable protected final SourceClass doProcessConfigurationClass( ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter) throws IOException { if (configClass.getMetadata().isAnnotated(Component.class.getName())) { // Recursively process any member (nested) classes first processMemberClasses(configClass, sourceClass, filter); } // Process any @PropertySource annotations for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable( sourceClass.getMetadata(), PropertySources.class, org.springframework.context.annotation.PropertySource.class)) { if (this.environment instanceof ConfigurableEnvironment) { processPropertySource(propertySource); } else { logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() + "]. Reason: Environment must implement ConfigurableEnvironment"); } } // Process any @ComponentScan annotations Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable( sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class); if (!componentScans.isEmpty() && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) { for (AnnotationAttributes componentScan : componentScans) { // The config class is annotated with @ComponentScan -> perform the scan immediately Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName()); // Check the set of scanned definitions for any further config classes and parse recursively if needed for (BeanDefinitionHolder holder : scannedBeanDefinitions) { BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition(); if (bdCand == null) { bdCand = holder.getBeanDefinition(); } if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) { parse(bdCand.getBeanClassName(), holder.getBeanName()); } } } } // Process any @Import annotations processImports(configClass, sourceClass, getImports(sourceClass), filter, true); // Process any @ImportResource annotations AnnotationAttributes importResource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class); if (importResource != null) { String[] resources = importResource.getStringArray("locations"); Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader"); for (String resource : resources) { String resolvedResource = this.environment.resolveRequiredPlaceholders(resource); configClass.addImportedResource(resolvedResource, readerClass); } } // Process individual @Bean methods Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass); for (MethodMetadata methodMetadata : beanMethods) { configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass)); } // Process default methods on interfaces processInterfaces(configClass, sourceClass); // Process superclass, if any if (sourceClass.getMetadata().hasSuperClass()) { String superclass = sourceClass.getMetadata().getSuperClassName(); if (superclass != null && !superclass.startsWith("java") && !this.knownSuperclasses.containsKey(superclass)) { this.knownSuperclasses.put(superclass, configClass); // Superclass found, return its annotation metadata and recurse return sourceClass.getSuperClass(); } } // No superclass -> processing is complete return null; }
12. Spring ASM
bid: 2022121615335100000000000010
asm
在spring中其实很少听到asm这个关键字,asm -> Assembly,跟多是指汇编语言。
spring也是用到asm,而且asm包是spring-core的组成部分。spring asm 大体上跟 原生的asm 都是差不多了。
package org.springframework.asm
Spring's repackaging of ASM 9.x (with Spring-specific patches; for internal use only).
This repackaging technique avoids any potential conflicts with dependencies on ASM at the application level or from third-party libraries and frameworks.
As this repackaging happens at the class file level, sources and javadocs are not available here.
从package-info可以看出,repackaging,avoids any potential conflicts
13. PostProcessorRegistrationDelegate
bid: 2022121915527600000000000011
PostProcessorRegistrationDelegate
作为 Delegate 提供了 静态方法 invokeBeanFactoryPostProcessors。
主要是将beanFactory和beanFactoryPostProcessors做matching, 然后对beanFactoryPostProcessors做遍历调用postProcessBeanFactory(beanFactory)
ConfigurationClassPostProcessor
postProcessBeanFactory(beanFactory)
processConfigBeanDefinitions(beanFactory)
核心的 处理方法,
14. Spring Aop
bid: 2022122715594900000000000012
Aop
Aspect Oriented Programming的缩写,意为:面向切面编程。 Spring aop 作为spring的一个模块,在springboot中是在bean的实例化中使用的。
AbstractAutowireCapableBeanFactory#initializeBean
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
# 实现了Aware接口<BeanNameAware><BeanClassLoaderAware><BeanFactoryAware>会invoke对应的set方法。
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
# beanPostProcesser的before方法。
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
# 实现了InitializingBean接口的会invoke afterPropertiesSet方法。
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()) {
# beanPostProcesser的after方法。
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
AbstractAdvisingBeanPostProcessor#postProcessAfterInitialization
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (this.advisor == null || bean instanceof AopInfrastructureBean) {
// Ignore AOP infrastructure such as scoped proxies.
return bean;
}
if (bean instanceof Advised) {
Advised advised = (Advised) bean;
if (!advised.isFrozen() && isEligible(AopUtils.getTargetClass(bean))) {
// Add our local Advisor to the existing proxy's Advisor chain...
if (this.beforeExistingAdvisors) {
advised.addAdvisor(0, this.advisor);
}
else {
advised.addAdvisor(this.advisor);
}
return bean;
}
}
if (isEligible(bean, beanName)) {
ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName);
if (!proxyFactory.isProxyTargetClass()) {
evaluateProxyInterfaces(bean.getClass(), proxyFactory);
}
proxyFactory.addAdvisor(this.advisor);
customizeProxyFactory(proxyFactory);
// Use original ClassLoader if bean class not locally loaded in overriding class loader
ClassLoader classLoader = getProxyClassLoader();
if (classLoader instanceof SmartClassLoader && classLoader != bean.getClass().getClassLoader()) {
classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
}
# ProxyFactory 其实就是创建动态代理或者Cglib的 InvocationHandler调用Proxy.newProxyInstance返回代理对象
return proxyFactory.getProxy(classLoader);
}
// No proxy needed.
return bean;
}