0%

湘湖

图片拍摄于2021年1月2日 杭州湘湖。 如果杭州不那么奋斗的话,还是很宜居的。小声逼逼

BeanFactory

解析

1
BeanFactory bf = new XmlBeanFactory(new ClassPathResource("beanFacotryTest.xml"));
1
this(resource, parent);
1
2
3
4
super(parentFactory);

this.reader.loadBeanBeanDenefinaction(resource);

loadBeanBeanDenefinaction 的作用是判断xml的编码方式,然后将Resource 包装成合适的org.xml.sax.Input

之后调用

XmlBeanDenefinactionReader#doLoadBeanDenefinaction(input, Resource resource)

在这个方法中主要的步骤是

int validationMode = getValidDationModeForResource(resource);

确定xml文件的验证方式。是DTD 还是XSD确定的方式也很简单 检查readLine 确定是否有这样的开头的String<! DOCTYPE….> 如果有的话就是DTD,没有的话就是XSD

Document doc = this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());

之后调用

XmlBeanDenefinactionReader#registerBeanDefinitions(doc, resource);

在这个方法里面将解析的任务交给BeanDefinitionDocumentReader 执行, 然后得doc解析完成之后新增的BeanDefinaction的数量

这时候已经将xml文档变成了Document文档

之后调用

DefaultBeanDefinitionDocumentReader#registerBeanDefinitions(doc, readerContext);

这个方法主要的作用是 解析Root 标签(beans) 得到Element标签

之后调用

DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions()

BeanDefinitionParserDelegate delegate = createDelegate(getReaderContext(), root, parent);

创建解析代理。 在createDelegate中会解析Bean 的attribute。比方说 default-lazy-init

parseBeanDefinitions(root, this.delegate);

得到root的子元素,然后根据节点的名称

  1. BeanDefinitionParserDelegate#parseDefaultElement

    beans bean alias import

  2. BeanDefinitionParserDelegate#parseCustomElement

    自定义的标签 比方说 context:component-scan aop:aspect-autoproxy

解析bean

BeanDefinitionHolder bdHoler = parseBeanDefinitionElement(element)

解析id attribute

解析 name attribute

解析1. scope 2.singleton 3. lazy-init 4. autowire 5.dependency-check 6. depend-on 7. auto-candidate 8.primary

  1. init-method 10. destory-method 11. factory-method 12. factory-bean

parseBeanDenefinitionElement(ele, beanName, containingBean);

parseMetaElements

解析元数据

parseLookupOverrideSubElements

解析 lookup - method, 原始的class 是abstract class A, 然后有这个abstract的实现类 Aa

在定义Bean的时候可以

1
2
3
<bean .....>
<lookup-method name = "" bean=""/>
</bean>

解析replace-method 属性

和 replace-method 不一样的点是 要替代的方法要实现MethodReplacer接口

解析构造函数参数

解析property

解析qualifer

最后连同AbstractBeanDefinition (实际上是 GenericBeanDefinition ), beanName 和aliansList 创建BeanefinitionHolder

之后调用

BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());

其中getReaderContext() 是之前的XmlBeanFactory。而XmlBeanFactory的构造函数是

public XmlBeanDefinitionReader(BeanDefinitionRegistry registry);

XmlBeanFactory 是BeanDefinitionRegistry 的子类

函数的作用是将BeanDenefinition注册到register的BeanDenefinition 中。将alians 注册到alians Map中。

由此Bean解析完成

解析Alians

getReaderContext().getRegisty().registerAlias(name, alias);

解析Import

getReaderContext().getResource().loadBeanDefinitions(StringUtils.applyRelativePath(baseLocation, locations));

解析自定义标签

  1. 告诉Spring怎么验证xml的标签是否正确
  2. 告诉Spring 怎么解析标签

在META-INF 文件夹中创建

Spring.handers

http://blog.andrewchen1.top/schema/user=top.andrewchen1.blog.UserNamespaceHander

其中UserNamespaceHande extends NamespaceHandlerSupport.

在Spring.schemas 中指定xsd的解析方式

http://blog.andrewchen1.top/schema/user.xsd=META-INF/user.xsd

image-20201209165024576

1
2
3
4
5
http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler
http\://www.springframework.org/schema/jee=org.springframework.ejb.config.JeeNamespaceHandler
http\://www.springframework.org/schema/lang=org.springframework.scripting.config.LangNamespaceHandler
http\://www.springframework.org/schema/task=org.springframework.scheduling.config.TaskNamespaceHandler
http\://www.springframework.org/schema/cache=org.springframework.cache.config.CacheNamespaceHandler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class ContextNamespaceHandler extends NamespaceHandlerSupport {

@Override
public void init() {
registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
public BeanDefinition parse(Element element, ParserContext parserContext) {
String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);
basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);

// Actually scan for bean definitions and register them.
ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
registerComponents(parserContext.getReaderContext(), beanDefinitions, element);

return null;
}

Spring IoC:context:component-scan 节点详解

扫描baseBackage下被org.springframework.stereotype.Component.class, javax.annotation.ManagedBean,javax.inject.Named 中修饰的类,然后生成BeanDefinitionHolder,最后注册到BeanFactory中

## 加载Bean
1
MyTestBean myTestBean = bf.getBean("myTestBean");

protected T doGetBean(final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly);

  1. getBeanName 根据BeanName的生成规则生成BeanName,如果是FactoryBean的话生成的BeanName是以&开头的

  2. 将BeanName中如果存在& 将& 去掉

  3. 根据修改过的BeanName,通过getSingleton方法到缓存中获取对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
    synchronized (this.singletonObjects) {
    singletonObject = this.earlySingletonObjects.get(beanName);
    if (singletonObject == null && allowEarlyReference) {
    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
    if (singletonFactory != null) {
    singletonObject = singletonFactory.getObject();
    this.earlySingletonObjects.put(beanName, singletonObject);
    this.singletonFactories.remove(beanName);
    }
    }
    }
    }
    return singletonObject;
    }
    1. 如果找到了执行 getObjectForBeanInstance() 方法

      bean的实际名称&开头 bean的实际名称不是&开头
      isInstance Of FactoryBean 直接返回 抛错
      ! InstanceOf FactoryBean 抛错 在factoryBeanObjectCache缓存检查是否存在如果存在直接返回
      如果不存在
      1.将对象强制类型转换为FactoryBean
      2. 调用getObject 方法
      3.得到工厂生成的实例后,调用postProcessObjectFromFactoryBean(实际是BeanPostProcessor#postProcessAfterInitialization)
      4.将得到的对象缓存到factoryBeanObjectCache缓存中
    2. 如果不存在 进行Bean 实例的生成

      1. 将Bean 由GernericBeanDefinition 转换为RootBeanDefinition

      2. 检查RootBeanDefiniition中dependsOn的Bean。先将depenesOn的Bean生成

      3. 调用 Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) 得到sharedInstance.

        1. 执行方法singletonFactory#getObject()

        2. 然后放到singleObject中

          1
          2
          3
          4
          5
          6
          7
          8
          protected void addSingleton(String beanName, Object singletonObject) {
          synchronized (this.singletonObjects) {
          this.singletonObjects.put(beanName, singletonObject);
          this.singletonFactories.remove(beanName);
          this.earlySingletonObjects.remove(beanName);
          this.registeredSingletons.add(beanName);
          }
          }
singletonFactory.getObject实际上是在步骤3中的singletonFactory的匿名对象生成的类。getObject 实际上是调用AbstractBeanFactory#createBean

1. 检查这个类是否可以快捷的创建

   - beforeInstantiationResolved还没有设置或者是false
   - 这个类是原生的类 没有被代理过的类
   - 存在BeanPostProcessor

   resolveBeforeInstantantiation给BeanPostProcessors一个机会来返回代理来代理真正的实例

   **bean 的实例化前调用,也就是将AbstractBeanDefinition 转化为BeanWrapper 的前处理,给了子类一个修改BeanDenefinition的机会 **

2. 否则调用 doCreateBean

   1. createBeanInstance 通过constructor-arg 或者通过默认构造函数进行实例的创建

   2. 在允许提前曝光的情况下 创建ObjectFactory

      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
3. 填充属性 4. initializeBean 1. 实现是否是BeanNameAware BeanClassLoaderAware BeanFactoryAware 的实现。其他的类似于ApplicationContextWare。来自于ApplicationContextAwareProcessor。 2. 调用BeanDenefinaction 中定义的init方法 ​ 然后调用方法getObjectForBeanInstance()

Bean的循环依赖

有 A 属性中有依赖于B。 B中有属性依赖A。A和B通过默认构造器进行构造。

A首先生成A的ObjectFactory 注册到ObjectFactories中,

在填充属性的时候发现B的实例在容器中还没有生成

开始B的实例化生成动作

在填充属性A的时候 可以在ObjectFactory 中得到A的ObjectFactory, 通过A的ObjectFactory生成A的属性还没有填充完成的实例(此实例是执行完成BeanPostProcessor#getEarlyBeanReference),将此实例放到earlyObjectsMap 中

B的实例生成完成将实例放到singletonObjects 同时返回

继续A的属性填充流程

A的属性填充完成

A的实例生成完成

ClassPathXmlApplication

在BeanFactory 的基础上提供了国际化和事件的支持

1
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(path);
1
this(new String[] {configLocation}, true, null);
1
2
3
4
5
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}

prepareRefresh

通过子类进行覆盖 主要是属性的验证

obtainFreshBeanFactory

构建BeanFactory 同时解析BeanDenefinaction

prepareBeanFactory

进行属性的填充类似于classLoader beanPostProcessor

注册BeanExpressionResolver 支持SPEL

注册属性注册器 比方说一个属性是Date。xml 中写的是String。通过属性注册器进行适配

public interface PropertyEditorSupport

添加ApplicationContextAwareProcessor 处理器 用来解析ApplicatonContextAware

postProcessBeanFactory

子类覆盖做一些额外的处理

比方说在GenericWebApplicationContext 就把beanFactory保存在servlet的环境变量中

invokeBeanFactoryPostProcessors

到BeanenefinactionRegister(BeanFactory) 中查找所有BeanFactoryPostProcessor 的实现。按照Order进行排序 然后进行接口调用。

比方说参数的替换。我们在定义jdbc Bean的时候是 ${mysql.password}。 这时候就通过Environment 中的实际值进行替换。

registerBeanPostProcessors

注册BeanPostProcessor

initMessageSource

消息国际化

initApplicationEventMulticaster

将SimpleApplicationEventMulticaster 注册到BeanFactory中

onRefresh

registerListeners

构建Event和listener之间的关系

finishBeanFactoryInitialization

得到所有的beanDefinitionNames.遍历getBean

finishRefresh

BeanFactory 和ApplicationContext 之间的差别

ApplicationContext 包含BeanFactory 并且

  • 支持国际化
  • 支持Listener

  • 同时加载多个配置文件

  • 可以有parent

  • bean 实例化的时机不一样 beanFactory 在getBean的时候进行实例化,而Application在finishBeanFactoryInitialization 进行初始化

  • ApplicationContext 支持自动注册BeanPostProcessor, 而BeanFactory 需要自行register

Spring Boot

打包

在编写spring boot 项目的时候往往会在pom的build 部分内加入

1
2
3
4
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>

在 Spring parent 中的定义是

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>${start-class}</mainClass>
</configuration>
</plugin>

在spring-boot-maven-plugin 中plugin.xml 中的定义

1
2
3
4
5
6
<mojo>
<goal>repackage</goal>
···
<phase>package</phase>
<implementation>org.springframework.boot.maven.RepackageMojo</implementation>
...

意味着在maven的package 阶段会执行RepackageMojo#execute 方法 然后对类重新打包,生成fat jar

Spring Boot jar可执行原理的彻底分析

目录格式为

├─BOOT-INF
│ ├─classes
│ └─lib
├─META-INF
│ ├─maven
│ ├─app.properties
│ ├─MANIFEST.MF
└─org
└─springframework
└─boot
└─loader
├─archive
├─data
├─jar
└─util

MAINFEST.MF

1
2
3
4
5
6
7
8
9
10
Manifest-Version: 1.0
Created-By: Maven Archiver 3.4.0
Build-Jdk-Spec: 11
Implementation-Title: demo
Implementation-Version: 0.0.1-SNAPSHOT
Main-Class: org.springframework.boot.loader.archive.Archive.JarLauncher
Start-Class: com.example.demo.DemoApplication
Spring-Boot-Version: 2.2.6.RELEASE
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/

启动

JarLauncher 主要做的事情是

  1. classLoader加载fat jar 中的 BOOT-INF/classes/ 和 BOOT-INF/lib/ 中的class 和*.jar

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    	static final String BOOT_INF_CLASSES = "BOOT-INF/classes/";

    static final String BOOT_INF_LIB = "BOOT-INF/lib/";

    protected boolean isNestedArchive(Archive.Entry entry) {
    if (entry.isDirectory()) {
    return entry.getName().equals(BOOT_INF_CLASSES);
    }
    return entry.getName().startsWith(BOOT_INF_LIB);
    }
  1. 执行Start-Class 中的 main 方法
1
2
3
4
5
6
7
8
9
10
11
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// classPath 中所有的 ApplicationContextInitializer.class 实例放到列表中 和 ApplicationListener.class
// 放到列表中,ApplicationContextInitializer.class和ApplicationListener.class定义在META-INF/spring.factories中
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
  1. 之后调用SpringApplication实例的run方法

    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
    public ConfigurableApplicationContext run(String... args) {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    ConfigurableApplicationContext context = null;
    Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
    configureHeadlessProperty();
    // 在META-INF/spring.factories中定义的lister的 包装成SpringApplicationRunListeners
    SpringApplicationRunListeners listeners = getRunListeners(args);
    listeners.starting();
    try {
    // 将args 包装成 ApplicationArguments
    ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
    // 生成环境 详细看后续说明
    ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
    //
    configureIgnoreBeanInfo(environment);
    Banner printedBanner = printBanner(environment);
    context = createApplicationContext();
    exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
    new Class[] { ConfigurableApplicationContext.class }, context);
    prepareContext(context, environment, listeners, applicationArguments, printedBanner);
    refreshContext(context);
    afterRefresh(context, applicationArguments);
    stopWatch.stop();
    if (this.logStartupInfo) {
    new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
    }
    listeners.started(context);
    callRunners(context, applicationArguments);
    }
    catch (Throwable ex) {
    handleRunFailure(context, ex, exceptionReporters, listeners);
    throw new IllegalStateException(ex);
    }

    try {
    listeners.running(context);
    }
    catch (Throwable ex) {
    handleRunFailure(context, ex, exceptionReporters, null);
    throw new IllegalStateException(ex);
    }
    return context;
    }

profile

在profile 中spring 会分析 enviorment 中 spring.profiles.active 和 spring.profiles.include的值。来确定要激活的profile。 在创建ApplicationContext的时候也能通过硬编码的方式指定active的profile

1
2
3
4
5
6
7
public static void main(String[] args) {
new SpringApplicationBuilder()
// 此时会给ApplicationContext的additionalProfiles属性设置值
.profiles("prod")
.build()
.run(AnotherMain.class, args);
}

在前述的prepareEnvironment() 步骤

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
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
// Create and configure the environment
ConfigurableEnvironment environment = getOrCreateEnvironment();
configureEnvironment(environment, applicationArguments.getSourceArgs());
ConfigurationPropertySources.attach(environment);
// 发送 ApplicationEnvironmentPreparedEvent 事件
// 能响应 ApplicationEnvironmentPreparedEvent 有
// 1. FileEncodingApplicationListener#onApplicationEvent
// 检查spring.mandatory-file-encoding 和系统的file.encoding的值是否一致,如果不一致就报错,主要是用来检查
// 2. AnsiOutputApplicationListener#onApplicationEvent 检查是否支持ANSI,如果是的话,用彩色的方式输出日志
// 激活 environmentPrepared 事件,主要是加载 application.property 等配置文件
// 3. ConfigFileApplicationListener#onApplicationEvent
// 3.1 查找所有在spring.factories 中声明的 EnvironmentPostProcessor的实现
// 比较常用的有 ConfigFileApplicationListener,其本身也是EnvironmentPostProcessor的实现
// 还有ApolloApplicationContextInitializer。我们用携程的apollo进行配置
//ConfigFileApplicationListener
// 在ConfigFileApplicationListener#postProcessEnvironment 方法中,将加载的配置的工作委托为通过内部类Loder进行。
// Loader 在构建的过程中会 确定 要使用的profile。 详细的部分见后续
// 通过SpringFactoriesLoader查找PropertySourceLoader的实现类。
// 默认Spring boot 提供的有PropertiesPropertySourceLoader 和YamlPropertySourceLoader
listeners.environmentPrepared(environment);
bindToSpringApplication(environment);
if (!this.isCustomEnvironment) {
environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
deduceEnvironmentClass());
}
ConfigurationPropertySources.attach(environment);
return environment;
}

protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
if (this.addConversionService) {
ConversionService conversionService = ApplicationConversionService.getSharedInstance();
environment.setConversionService((ConfigurableConversionService) conversionService);
}
// 解析 java -Dserver.port=8081 -jar spring.jar --server.port=8081
// 生成SimpleCommandLinePropertySource 加入到 Environment
// 检查 Environment 中active 的profice 并且进行设置
configurePropertySources(environment, args);
configureProfiles(environment, args);
}

protected void configureProfiles(ConfigurableEnvironment environment, String[] args) {
// 将硬编码的profile 加入到activeProfiles 中
Set<String> profiles = new LinkedHashSet<>(this.additionalProfiles);
profiles.addAll(Arrays.asList(environment.getActiveProfiles()));
environment.setActiveProfiles(StringUtils.toStringArray(profiles));
}

org.springframework.boot.context.config.ConfigFileApplicationListener#postProcessEnvironment

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
	@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
addPropertySources(environment, application.getResourceLoader());
}

protected void addPropertySources(ConfigurableEnvironment environment, ResourceLoader resourceLoader) {
RandomValuePropertySource.addToEnvironment(environment);
new Loader(environment, resourceLoader).load();
}

void load() {
FilteredPropertySource.apply(this.environment, DEFAULT_PROPERTIES, LOAD_FILTERED_PROPERTY,
(defaultProperties) -> {
this.profiles = new LinkedList<>();
this.processedProfiles = new LinkedList<>();
this.activatedProfiles = false;
this.loaded = new LinkedHashMap<>();
initializeProfiles();
while (!this.profiles.isEmpty()) {
Profile profile = this.profiles.poll();
if (isDefaultProfile(profile)) {
addProfileToEnvironment(profile.getName());
}
load(profile, this::getPositiveProfileFilter,
addToLoaded(MutablePropertySources::addLast, false));
this.processedProfiles.add(profile);
}
load(null, this::getNegativeProfileFilter, addToLoaded(MutablePropertySources::addFirst, true));
addLoadedPropertySources();
applyActiveProfiles(defaultProperties);
});
}

private void initializeProfiles() {
// The default profile for these purposes is represented as null. We add it
// first so that it is processed first and has lowest priority.
this.profiles.add(null);
//
Set<Profile> activatedViaProperty = getProfilesFromProperty(ACTIVE_PROFILES_PROPERTY);
Set<Profile> includedViaProperty = getProfilesFromProperty(INCLUDE_PROFILES_PROPERTY);
List<Profile> otherActiveProfiles = getOtherActiveProfiles(activatedViaProperty, includedViaProperty);
this.profiles.addAll(otherActiveProfiles);
// Any pre-existing active profiles set via property sources (e.g.
// System properties) take precedence over those added in config files.
this.profiles.addAll(includedViaProperty);
addActiveProfiles(activatedViaProperty);
if (this.profiles.size() == 1) { // only has null profile
for (String defaultProfileName : this.environment.getDefaultProfiles()) {
Profile defaultProfile = new Profile(defaultProfileName, true);
this.profiles.add(defaultProfile);
}
}
}

org.springframework.boot.context.config.ConfigFileApplicationListener.Loader#initializeProfiles

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
private void initializeProfiles() {
// The default profile for these purposes is represented as null. We add it
// first so that it is processed first and has lowest priority.
this.profiles.add(null);
// 通过 spring.profiles.active 激活的配置
Set<Profile> activatedViaProperty = getProfilesFromProperty(ACTIVE_PROFILES_PROPERTY);
// 通过spring.profiles.include 激活的配置
Set<Profile> includedViaProperty = getProfilesFromProperty(INCLUDE_PROFILES_PROPERTY);
// 不是上面两个配置内的 但是目前是激活状态的配置
List<Profile> otherActiveProfiles = getOtherActiveProfiles(activatedViaProperty, includedViaProperty);
this.profiles.addAll(otherActiveProfiles);
// Any pre-existing active profiles set via property sources (e.g.
// System properties) take precedence over those added in config files.
this.profiles.addAll(includedViaProperty);
addActiveProfiles(activatedViaProperty);
if (this.profiles.size() == 1) { // only has null profile
for (String defaultProfileName : this.environment.getDefaultProfiles()) {
Profile defaultProfile = new Profile(defaultProfileName, true);
this.profiles.add(defaultProfile);
}
}
}

Spring Boot 启动(二) Environment 加载

Aop

1
<aop:aspect-autoproxy/>

org.springframework.spring-aop:spring-aop:version

spring.handler 中

m
1
http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler

注册xml Element 解析器AspectJAutoProxyBeanDefinitionParser

AspectJAutoProxyBeanDefinitionParser 的主要作用是在 BeanFactory 中注册 AnnotationAwareAspectJAutoProxyCreator.class

JdbcTemplate

Mybatis

Transaction

Spring MVC

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.example.demo;



import org.springframework.beans.factory.BeanFactory;

import org.springframework.beans.factory.xml.XmlBeanFactory;

import org.springframework.core.io.ClassPathResource;

public class Main {
public static void main(String[] args) throws Exception {

BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("Beans.xml"));

beanFactory.getBean("myTestBean");
}

}

Resource

org.springframework.core.io.Resource
是对不同类型资源的封装 大体上想要拿到的就是那个资源的Inputstrem

XmlBeanFactory

1
2
3
4
public XmlBeanFactory(Resource resource, BeanFactory beanFactory) throws BeansException {
supre(beanFactory);
this.reader.loadBeanDefinitions(resource);
}

加载Bean

检查Bean 是不是已经被加载过了 如果没有就委托给XmlBeanDefinitionReader#doLoadBeanDefinitions进行实际类型的加载
XmlBeanDefinitionReader#loadBeanDefinitions

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
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isTraceEnabled()) {
logger.trace("Loading XML bean definitions from " + encodedResource);
}
// resource 这个已经被reader load过了
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}

try (InputStream inputStream = encodedResource.getResource().getInputStream()) {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}

实际加载BeanDefinitions

XmlBeanDefinitionReader#doLoadBeanDefinitions

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
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {

try {
// 解析xml 得到Document
Document doc = doLoadDocument(inputSource, resource);
int count = registerBeanDefinitions(doc, resource);
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + count + " bean definitions from " + resource);
}
return count;
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (SAXParseException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
"Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
}
catch (SAXException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
"XML document from " + resource + " is invalid", ex);
}
catch (ParserConfigurationException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Parser configuration exception parsing XML from " + resource, ex);
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"IOException parsing XML document from " + resource, ex);
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Unexpected exception parsing XML document from " + resource, ex);
}
}

解析Xml 获得Docuemnt对象

XmlBeanDefinitionReader#doLoadDocument

1
2
3
4
protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
getValidationModeForResource(resource), isNamespaceAware());
}

获取Resource的验证方式

xml的验证方式主要有DTD和XSD
读取每一行,如果行内有DOCTYPE 表示验证的方式是DTD 否则是XSD
XmlValidationModeDetector#detectValidationMode

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
/**
* Detect the validation mode for the XML document in the supplied {@link InputStream}.
* Note that the supplied {@link InputStream} is closed by this method before returning.
* @param inputStream the InputStream to parse
* @throws IOException in case of I/O failure
* @see #VALIDATION_DTD
* @see #VALIDATION_XSD
*/
public int detectValidationMode(InputStream inputStream) throws IOException {
// Peek into the file to look for DOCTYPE.
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
try {
boolean isDtdValidated = false;
String content;
while ((content = reader.readLine()) != null) {
content = consumeCommentTokens(content);
if (this.inComment || !StringUtils.hasText(content)) {
continue;
}
if (hasDoctype(content)) {
isDtdValidated = true;
break;
}
if (hasOpeningTag(content)) {
// End of meaningful data...
break;
}
}
return (isDtdValidated ? VALIDATION_DTD : VALIDATION_XSD);
}
catch (CharConversionException ex) {
// Choked on some character encoding...
// Leave the decision up to the caller.
return VALIDATION_AUTO;
}
finally {
reader.close();
}
}

设定解析Document的 DocumentBuilderFactory 和 DocumentBuilder

1
2
3
4
5
6
7
8
9
10
public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,
ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {

DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
if (logger.isTraceEnabled()) {
logger.trace("Using JAXP provider [" + factory.getClass().getName() + "]");
}
DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
return builder.parse(inputSource);
}

解析和注册BeanDefinitons

DefaultBeanDefinitionDocumentReader#registerBeanDefinitions

1
2
3
4
5
6
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}

解析Xml中的Beans

DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions

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
@SuppressWarnings("deprecation")  // for Environment.acceptsProfiles(String...)
protected void doRegisterBeanDefinitions(Element root) {
// Any nested <beans> elements will cause recursion in this method. In
// order to propagate and preserve <beans> default-* attributes correctly,
// keep track of the current (parent) delegate, which may be null. Create
// the new (child) delegate with a reference to the parent for fallback purposes,
// then ultimately reset this.delegate back to its original (parent) reference.
// this behavior emulates a stack of delegates without actually necessitating one.
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent);

if (this.delegate.isDefaultNamespace(root)) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
// We cannot use Profiles.of(...) since profile expressions are not supported
// in XML config. See SPR-12458 for details.
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isDebugEnabled()) {
logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +
"] not matching: " + getReaderContext().getResource());
}
return;
}
}
}

preProcessXml(root);
parseBeanDefinitions(root, this.delegate);
postProcessXml(root);

this.delegate = parent;
}

解析Beans 标签的attribute元素

Reader 中会生成ParserDelegate
DefaultBeanDefinitionDocumentReader#createDelegate

1
2
3
4
5
6
7
protected BeanDefinitionParserDelegate createDelegate(
XmlReaderContext readerContext, Element root, @Nullable BeanDefinitionParserDelegate parentDelegate) {

BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
delegate.initDefaults(root, parentDelegate);
return delegate;
}

BeanDefinitionParserDelegate#initDefaults

1
2
3
4
public void initDefaults(Element root, @Nullable BeanDefinitionParserDelegate parent) {
populateDefaults(this.defaults, (parent != null ? parent.defaults : null), root);
this.readerContext.fireDefaultsRegistered(this.defaults);
}

BeanDefinitionParserDelegate#populateDefaults

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
protected void populateDefaults(DocumentDefaultsDefinition defaults, @Nullable DocumentDefaultsDefinition parentDefaults, Element root) {
String lazyInit = root.getAttribute(DEFAULT_LAZY_INIT_ATTRIBUTE);
if (isDefaultValue(lazyInit)) {
// Potentially inherited from outer <beans> sections, otherwise falling back to false.
lazyInit = (parentDefaults != null ? parentDefaults.getLazyInit() : FALSE_VALUE);
}
defaults.setLazyInit(lazyInit);

String merge = root.getAttribute(DEFAULT_MERGE_ATTRIBUTE);
if (isDefaultValue(merge)) {
// Potentially inherited from outer <beans> sections, otherwise falling back to false.
merge = (parentDefaults != null ? parentDefaults.getMerge() : FALSE_VALUE);
}
defaults.setMerge(merge);

String autowire = root.getAttribute(DEFAULT_AUTOWIRE_ATTRIBUTE);
if (isDefaultValue(autowire)) {
// Potentially inherited from outer <beans> sections, otherwise falling back to 'no'.
autowire = (parentDefaults != null ? parentDefaults.getAutowire() : AUTOWIRE_NO_VALUE);
}
defaults.setAutowire(autowire);

if (root.hasAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE)) {
defaults.setAutowireCandidates(root.getAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE));
}
else if (parentDefaults != null) {
defaults.setAutowireCandidates(parentDefaults.getAutowireCandidates());
}

if (root.hasAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE)) {
defaults.setInitMethod(root.getAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE));
}
else if (parentDefaults != null) {
defaults.setInitMethod(parentDefaults.getInitMethod());
}

if (root.hasAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE)) {
defaults.setDestroyMethod(root.getAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE));
}
else if (parentDefaults != null) {
defaults.setDestroyMethod(parentDefaults.getDestroyMethod());
}

defaults.setSource(this.readerContext.extractSource(root));
}

Spring Boot应用打包

在编写spring boot 项目的时候往往会在pom的build 部分内加入

1
2
3
4
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>

其作用就是重新组织资源 使最终的结果物 无论是jar形式的还是 war形式的 都能 通过java -jar ***.jar(war)的命令启动。

在通过maven 打包的时候

首先按照会正常的流程编译,之后

spring-boot-maven-plugin 插件 会介入进行repackage

1
2
[INFO] --- spring-boot-maven-plugin:2.2.6.RELEASE:repackage (repackage) @ demo ---
[INFO] Replacing main artifact with repackaged archive

根据在pom 中 packaging 指定的类型不同 jar/war 重新组织文件的结构和内容

  1. 如果是war类型的

    对artifacts进行解压后会有如下的文件结构

    META-INF/ MAINFEST.MF

    META-INF/maven/com/example/demo/pom.properties

    META-INF/maven/com/example/demo/pom.xml

    WEB-INF/classes/*

    WEB-INF/lib/*

    org/springframework/boot/loader/*

    其中org/springframework/boot/loader/* 所代表的是下面这个包内的内容

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-loader</artifactId>
</dependency>

其作用是引导Spring Boot应用加载资源

同时会修改 MAINFEST.MF 的内容 ,值得注意的是Main class 并不是在程序里面写的入口类,而是Spring Boot提供的一个入口类

1
2
3
4
5
6
7
8
9
10
Manifest-Version: 1.0
Created-By: Maven Archiver 3.4.0
Build-Jdk-Spec: 11
Implementation-Title: demo
Implementation-Version: 0.0.1-SNAPSHOT
Main-Class: org.springframework.boot.loader.archive.Archive.WarLauncher
Start-Class: com.example.demo.DemoApplication
Spring-Boot-Version: 2.2.6.RELEASE
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
  1. 如果是jar 类型的

    对jar进行解压后会有如下的文件结构

    META-INF/ MAINFEST.MF

    META-INF/maven/com/example/demo/pom.properties

    META-INF/maven/com/example/demo/pom.xml

    BOOT-INF/classes/*

    BOOT-INF/lib/*

    org/springframework/boot/loader/*

    差异点有

    把WEB-INF 替换为 BOOT-INF

    MAINFEST.MF 中的Main-Class 为org.springframework.boot.loader.JarLauncher

Spring Boot项目启动

首先会加载 main-class 指定类的main方法。然后由其调用start-class 中的main方法

Main-Class部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected final Archive createArchive() throws Exception {
ProtectionDomain protectionDomain = getClass().getProtectionDomain();
CodeSource codeSource = protectionDomain.getCodeSource();
URI location = (codeSource != null) ? codeSource.getLocation().toURI() : null;
String path = (location != null) ? location.getSchemeSpecificPart() : null;
if (path == null) {
throw new IllegalStateException("Unable to determine code source archive");
}
File root = new File(path);
if (!root.exists()) {
throw new IllegalStateException("Unable to determine code source archive from " + root);
}
return (root.isDirectory() ? new ExplodedArchive(root) : new JarFileArchive(root));
}
  • Launcher

    这个类的作用是加载程序。JarLauncher 和 WarLauncher 都是继承于ExecutableArchiveLauncher

    在ExecutableArchiveLauncher的构造方法中调用

    Launcher#createArchive

    根据当前class的位置是在文件中还是文件夹中 判断程序jar类型的还是war类型的

    如果是jar类型的 文件组织方式是 /BOOT-INF/lib /BOOT-INF/classes

    如果是war类型的 文件的组织方式是 WEB-INF/lib WEB-INF/classes

    生成对应的 JarFileArchive ExplodedArchive 供后续的文件遍历使用

    父类加载完成 子类的构造函数中(JarLauncher / WarLauncher)中并没有什么内容

    举个例子

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class Main {
    public static void main(String[] args) throws Exception {
    ProtectionDomain protectionDomain = Main.class.getProtectionDomain();
    CodeSource codeSource = protectionDomain.getCodeSource();
    URI location = (codeSource != null) ? codeSource.getLocation().toURI() : null;
    System.out.println(location);
    String path = (location != null) ? location.getSchemeSpecificPart() : null;
    System.out.println(path);
    }
    }

    输出的结果是

    file:/Users/andrewchen1/Downloads/demo/target/classes/
    /Users/andrewchen1/Downloads/demo/target/classes/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static void main(String[] args) throws Exception {
new JarLauncher().launch(args);
}
protected void launch(String[] args) throws Exception {
JarFile.registerUrlProtocolHandler();
ClassLoader classLoader = createClassLoader(getClassPathArchives());
launch(args, getMainClass(), classLoader);
}
@Override
protected List<Archive> getClassPathArchives() throws Exception {
List<Archive> archives = new ArrayList<>(this.archive.getNestedArchives(this::isNestedArchive));
postProcessClassPathArchives(archives);
return archives;
}
  • getClassPathArchives

    对于jar 通过jarEntry 遍历jar中的所有内容 将 BOOT-INF/classes/ 和 BOOT-INF/lib/路径下的内容返回到list中

    对于explored war 通过遍历root path 下的所有内容 将WEB-INF/classes/和WEB-INF/lib/, WEB-INF/lib-provided/

    jar

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    public List<Archive> getNestedArchives(EntryFilter filter) throws IOException {
    List<Archive> nestedArchives = new ArrayList<>();
    for (Entry entry : this) {
    if (filter.matches(entry)) {
    nestedArchives.add(getNestedArchive(entry));
    }
    }
    return Collections.unmodifiableList(nestedArchives);
    }
    // 能 for (Entry entry : this) 的原因是 JarFileArchive的超类Archive 实现了Iterable<Archive.Entry> 接口

    @Override
    public Iterator<Entry> iterator() {
    return new EntryIterator(this.jarFile.entries());
    }

    // EntryIterator # hasNext方法
    public boolean hasNext() {
    return this.enumeration.hasMoreElements();
    }

    explored war

    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
    @Override
    public List<Archive> getNestedArchives(EntryFilter filter) throws IOException {
    List<Archive> nestedArchives = new ArrayList<>();
    for (Entry entry : this) {
    if (filter.matches(entry)) {
    nestedArchives.add(getNestedArchive(entry));
    }
    }
    return Collections.unmodifiableList(nestedArchives);
    }
    // 能 for (Entry entry : this) 的原因是 JarFileArchive的超类Archive 实现了Iterable<Archive.Entry> 接口
    @Override
    public Iterator<Entry> iterator() {
    return new FileEntryIterator(this.root, this.recursive);
    }
    // FileEntryIterator # hasNext方法
    @Override
    public Entry next() {
    if (this.current == null) {
    throw new NoSuchElementException();
    }
    File file = this.current;
    if (file.isDirectory() && (this.recursive || file.getParentFile().equals(this.root))) {
    this.stack.addFirst(listFiles(file));
    }
    this.current = poll();
    String name = file.toURI().getPath().substring(this.root.toURI().getPath().length());
    return new FileEntry(name, file);
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static void main(String[] args) throws Exception {
new JarLauncher().launch(args);
}
protected void launch(String[] args) throws Exception {
JarFile.registerUrlProtocolHandler();
ClassLoader classLoader = createClassLoader(getClassPathArchives());
launch(args, getMainClass(), classLoader);
}
protected ClassLoader createClassLoader(List<Archive> archives) throws Exception {
List<URL> urls = new ArrayList<>(archives.size());
for (Archive archive : archives) {
urls.add(archive.getUrl());
}
return createClassLoader(urls.toArray(new URL[0]));
}
protected ClassLoader createClassLoader(URL[] urls) throws Exception {
return new LaunchedURLClassLoader(urls, getClass().getClassLoader());
}

这部分的内容不多 就是创建一个类加载器 加载资源

//TODO classload 坑等待填 好怕怕的类加载器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public static void main(String[] args) throws Exception {
new JarLauncher().launch(args);
}
protected void launch(String[] args) throws Exception {
JarFile.registerUrlProtocolHandler();
ClassLoader classLoader = createClassLoader(getClassPathArchives());
launch(args, getMainClass(), classLoader);
}
protected void launch(String[] args, String mainClass, ClassLoader classLoader) throws Exception {
Thread.currentThread().setContextClassLoader(classLoader);
createMainMethodRunner(mainClass, args, classLoader).run();
}
protected MainMethodRunner createMainMethodRunner(String mainClass, String[] args, ClassLoader classLoader) {
return new MainMethodRunner(mainClass, args);
}
public MainMethodRunner(String mainClass, String[] args) {
this.mainClassName = mainClass;
this.args = (args != null) ? args.clone() : null;
}
public void run() throws Exception {
Class<?> mainClass = Thread.currentThread().getContextClassLoader().loadClass(this.mainClassName);
Method mainMethod = mainClass.getDeclaredMethod("main", String[].class);
mainMethod.invoke(null, new Object[] { this.args });
}

Start-Class 部分

SpringApplication.run(Application.class, args);

创建SpringApplication

  1. 确定resourceLoader (which is null)
  2. 确定primarySource (就是我们写main方法的那个类)
  3. 确定WebApplicationType (通过Class.ForName方法确认ClassLoader 中是否加载过特定的类,通过这个方法确定WebApplicationType)
  4. 通过spring.factories的方式获得要加载的ApplicationContextInitializer和ApplicationListener
  5. 确定MainApplicationClass (这个获取的方式很有意思 是通过生成一个RuntimeExcetpion的方式通过获得strackTrace 得到有main方法的那个类)

触发SpringApplication 的run方法

  1. 触发所有的ApplicationListener的starting方法

  2. 解析命令行形式的参数,解析成source内容,放到Enviorment 中

  3. 解析Enviorment中profile的内容

  4. 触发所有的ApplicationListener的environmentPrepared方法

  5. 根据WebApplicationType 获得要生成的ApplicationContext,要生成的ApplicationContext的父类GenericApplicationContext的构造方法中会生成DefaultListableBeanFactory

  6. 准备ApplicationContext

    1. 设置ApplicationContext的Enviorment
    2. 设置beanNameGenerator,resourceLoader
    3. 触发ApplicationContextInitializer, 像Apollo,spring cloud config center就是在这个时候获取远端的config,把它加入到Enviorment中
    4. 触发ApplicationListener的contextPrepared的方法
    5. 设置ConfigurableListableBeanFactory
    6. 触发ApplicationListener的contextLoaded方法
  7. 刷新Context

    1. prepareRefresh

      1. 初始化earlyApplicationListeners,初始值来自于applicationListeners
      2. 初始化earlyApplicationEvents
    2. obtainFreshBeanFactory

      1. loadBeanDefinitions
        1. loadBeanDefinitions
    3. prepareBeanFactory

      1. 设置factory的beanClassLoader,BeanExpressionResolver(类解析器),ResourceEditorRegistrar(配置解析器)
      2. 设置factory 哪些类(这些类生成了特定的接口 比方说ApplicationContextAware)是不用生成bean的
    4. postProcessBeanFactory

      在beanFactory生成之后

    5. invokeBeanFactoryPostProcessor

注册Bean

解析Bean

BeanDefinitionReaderUtils#registerBeanDefinition

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {

// Register bean definition under primary name.
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

// Register aliases for bean name, if any.
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}

DefaultListableBeanFactory#registerBeanDefinition

Bean 是注册在beanDefinitionMap 这个Map中的

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {

Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");

if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}

BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (logger.isInfoEnabled()) {
logger.info("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(existingDefinition)) {
if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
// 保护beanDefinitionMap
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);
}
}

自定义标签解析

如何使用

  • 定义一个POJO

    1
    2
    3
    4
    5
    6
    @Data
    public class User {
    private Long id;
    private String userName;
    private String email;
    }
  • 定义标签的XSD user.xsd

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <?xml version="1.0"?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://blog.andrewchen1.top/user"
    elementFormDefault="qualified">
    <xs:element name="user">
    <xs:complexType>
    <xs:attribute name="id" type="xs:string"/>
    <xs:attribute name="userName" type="xs:string"/>
    <xs:attribute name="email" type="xs:string"/>
    </xs:complexType>
    </xs:element>
    </xs:schema>
  • 定义parse

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    public class UserBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
    @Override
    protected Class<?> getBeanClass(Element element) {
    return User.class;
    }

    @Override
    protected void doParse(Element element, BeanDefinitionBuilder builder) {
    String userName = element.getAttribute("userName");
    String email = element.getAttribute("email");
    Long id = Long.valueOf(element.getAttribute("id"));

    builder.addPropertyValue("userName", userName);
    builder.addPropertyValue("email", email);
    builder.addPropertyValue("id", id);
    }
    }
  • 注册parse handler

    1
    2
    3
    4
    5
    6
    public class MyNamespaceHandler extends NamespaceHandlerSupport {
    @Override
    public void init() {
    registerBeanDefinitionParser("user", new UserBeanDefinitionParser());
    }
    }
  • 在META-INF/spring.handler中 (这个位置是代码写死的)

    http://blog.andrewchen1.top/user=com.example.demo.MyNamespaceHandler

  • 在META-INF/Spring.schemas中 (这个位置是代码写死的)

    http://blog.andrewchen1.top/user.xsd=user.xsd

1
2
3
4
5
6
7
8
9
10
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:myname="http://blog.andrewchen1.top/user"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://blog.andrewchen1.top/user
http://blog.andrewchen1.top/user.xsd
">
<user id = "1" name = "andrew" email = "andrew@andrewchen1.top"/>
</beans>

实现

BeanDefinitionParserDelegate#parseCustomElement

1
2
3
4
5
6
7
8
9
10
11
12
13
@Nullable
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
String namespaceUri = getNamespaceURI(ele);
if (namespaceUri == null) {
return null;
}
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}

DefaultNamespaceHandlerResolver#resolve

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
@Nullable
public NamespaceHandler resolve(String namespaceUri) {
Map<String, Object> handlerMappings = getHandlerMappings();
Object handlerOrClassName = handlerMappings.get(namespaceUri);
if (handlerOrClassName == null) {
return null;
}
else if (handlerOrClassName instanceof NamespaceHandler) {
return (NamespaceHandler) handlerOrClassName;
}
else {
String className = (String) handlerOrClassName;
try {
Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
"] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
}
NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
namespaceHandler.init();
handlerMappings.put(namespaceUri, namespaceHandler);
return namespaceHandler;
}
catch (ClassNotFoundException ex) {
throw new FatalBeanException("Could not find NamespaceHandler class [" + className +
"] for namespace [" + namespaceUri + "]", ex);
}
catch (LinkageError err) {
throw new FatalBeanException("Unresolvable class definition for NamespaceHandler class [" +
className + "] for namespace [" + namespaceUri + "]", err);
}
}
}
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
private Map<String, Object> getHandlerMappings() {
Map<String, Object> handlerMappings = this.handlerMappings;
if (handlerMappings == null) {
synchronized (this) {
handlerMappings = this.handlerMappings;
if (handlerMappings == null) {
if (logger.isTraceEnabled()) {
logger.trace("Loading NamespaceHandler mappings from [" + this.handlerMappingsLocation + "]");
}
try {
// handlerMappingsLocation 的值为META-INF/spring.handlers
Properties mappings =
PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
if (logger.isTraceEnabled()) {
logger.trace("Loaded NamespaceHandler mappings: " + mappings);
}
handlerMappings = new ConcurrentHashMap<>(mappings.size());
CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings);
this.handlerMappings = handlerMappings;
}
catch (IOException ex) {
throw new IllegalStateException(
"Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex);
}
}
}
}
return handlerMappings;
}

ListableBeanFactory 和 bean

以ListableBeanFactory 进行说明

doGetBean

bean factory 默认是lazy fetch的

AbstractBeanFactory#doGetBean

getSingleton [循环依赖 getSingleton](#getSingleton 循环依赖)

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// 如果Bean的名字是&开始的 要去掉& 然后到aliasMap找到beanName
// 比方说那么是&a&b&c&d 那么最后得到的beanName 是d
final String beanName = transformedBeanName(name);
Object bean;

// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
// 返回对应的实例,有时候存在BeanFactory的情况下不是直接返回实例本身而是返回BeanFactory指定方法返回的实例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}

else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
// 只有在单例模式的情况下才解决循环依赖,如果是原型模式的话就直接抛错。
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}

// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}

try {
// 将存储XML配置文件的GernericBeanDefinition 转化为RootBeanDefinition, 如果指定的BeanName 是子Bean的话会同时合并父类的相关属性
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);

// Guarantee initialization of beans that the current bean depends on.
// 比方说 a dependsOn b,b dependsOn c
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.
// @Depends的都创建好了,可以创建自己了
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;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}

else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}

// Check if required type matches the type of the actual bean instance.
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}

getSingleton 循环依赖

Spring解决循环依赖,你真的懂了吗?

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
 /**一级缓存,用于存放完全初始化好的 bean,从该缓存中取出的 bean 可以直接使用*/
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/**二级缓存 存放原始的 bean 对象(尚未填充属性),用于解决循环依赖*/
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
/**三级缓存 存放 bean 工厂对象,用于解决循环依赖*/
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

//getSingleton源码,DefaultSingletonBeanRegistry#getSingleton
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//先从一级缓存中获取已经实例化属性赋值完成的Bean
Object singletonObject = this.singletonObjects.get(beanName);
//一级缓存不存在,并且Bean正处于创建的过程中
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
//从二级缓存中查询,获取Bean的早期引用,实例化完成但是未赋值完成的Bean
singletonObject = this.earlySingletonObjects.get(beanName);
//二级缓存中不存在,并且允许创建早期引用(二级缓存中添加)
if (singletonObject == null && allowEarlyReference) {
//从三级缓存中查询,实例化完成,属性未装配完成
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
//二级缓存中添加
this.earlySingletonObjects.put(beanName, singletonObject);
//从三级缓存中移除
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;

返回 doGetBean

getObjectForBeanInstance

AbstractBeanFactory#getObjectForBeanInstance

得到的有可能是bean it self 但是有可能得到还是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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// 这里的name
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

// Don't let calling code try to dereference the factory if the bean isn't a factory.
// 如果name里面有& 说明要的就是FactoryBean 那么我们直接返回FactoryBean 就好了
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
// 虽然name有& 但是Bean的类型不是FactoryBean 那么一定是出错了
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
if (mbd != null) {
mbd.isFactoryBean = true;
}
return beanInstance;
}

// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the
// caller actually wants a reference to the factory.
// 如果bean的name里面没有& 并且 bean instance 也不是FactoryBean的实现
if (!(beanInstance instanceof FactoryBean)) {
return beanInstance;
}
// 第三种情况 就是name 是没有& 但是得到的BeanDefinition是FactoryBean
Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {
//private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>(16);
// 查看根据bean 那么是不是已经找到了RootBeanDefinition 如果不是的话 构建RootBeanDefinition
// 根据Bean
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}

getMergedLocalBeanDefinition

AbstractBeanFactory#getMergedLocalBeanDefinition

要把BeanDefinition 转化为RootBeanDefinition

1
2
3
4
5
6
7
8
9
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
// Quick check on the concurrent map first, with minimal locking.
// 已经merge 好了
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
if (mbd != null && !mbd.stale) {
return mbd;
}
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}

AbstractBeanFactory#getMergedBeanDefinition

这时候主要要做的事情就是把parentBeanDefinition的值赋值给itself

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
protected RootBeanDefinition getMergedBeanDefinition(
String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
throws BeanDefinitionStoreException {

synchronized (this.mergedBeanDefinitions) {
RootBeanDefinition mbd = null;
RootBeanDefinition previous = null;

// Check with full lock now in order to enforce the same merged instance.
if (containingBd == null) {
mbd = this.mergedBeanDefinitions.get(beanName);
}
// 是不是已经被转换成了RootBeanDefinitions了,如果不是 继续转换流程
if (mbd == null || mbd.stale) {
previous = mbd;
if (bd.getParentName() == null) {
// Use copy of given root bean definition.
if (bd instanceof RootBeanDefinition) {
mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
}
else {
mbd = new RootBeanDefinition(bd);
}
}
else {
// Child bean definition: needs to be merged with parent.
BeanDefinition pbd;
try {
String parentBeanName = transformedBeanName(bd.getParentName());
if (!beanName.equals(parentBeanName)) {
pbd = getMergedBeanDefinition(parentBeanName);
}
else {
BeanFactory parent = getParentBeanFactory();
if (parent instanceof ConfigurableBeanFactory) {
pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
}
else {
throw new NoSuchBeanDefinitionException(parentBeanName,
"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
"': cannot be resolved without a ConfigurableBeanFactory parent");
}
}
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
}
// Deep copy with overridden values.
mbd = new RootBeanDefinition(pbd);
mbd.overrideFrom(bd);
}

// Set default singleton scope, if not configured before.
if (!StringUtils.hasLength(mbd.getScope())) {
mbd.setScope(SCOPE_SINGLETON);
}

// A bean contained in a non-singleton bean cannot be a singleton itself.
// Let's correct this on the fly here, since this might be the result of
// parent-child merging for the outer bean, in which case the original inner bean
// definition will not have inherited the merged outer bean's singleton status.
if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
mbd.setScope(containingBd.getScope());
}

// Cache the merged bean definition for the time being
// (it might still get re-merged later on in order to pick up metadata changes)
if (containingBd == null && isCacheBeanMetadata()) {
this.mergedBeanDefinitions.put(beanName, mbd);
}
}
if (previous != null) {
copyRelevantMergedBeanDefinitionCaches(previous, mbd);
}
return mbd;
}
}

返回getObjectForBeanInstance

getObjectFromFactoryBean

AbstractBeanFactory#getObjectFromFactoryBean

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
56
57
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
if (factory.isSingleton() && containsSingleton(beanName)) {
// sychronized singletonObjects
synchronized (getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
//执行Factory#getObject方法得到 对象
object = doGetObjectFromFactoryBean(factory, beanName);
// Only post-process and store if not put there already during getObject() call above
// (e.g. because of circular reference processing triggered by custom getBean calls)
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (shouldPostProcess) {
if (isSingletonCurrentlyInCreation(beanName)) {
// Temporarily return non-post-processed object, not storing it yet..
return object;
}
// 把这个BeanFactory放到singletonsCurrentlyInCreation map 中表示这个Bean正在被创建
beforeSingletonCreation(beanName);
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
finally {
afterSingletonCreation(beanName);
}
}
// 这个Bean注册好了之后放到 factoryBeanObjectCache 中
if (containsSingleton(beanName)) {
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
}
// 如果不是singleton 不是单例的话
// 执行BeanFactory的get方法,然后得到的Object 执行BeanPostProcessor
else {
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}

返回getObjectForBeanInstance

postProcessObjectFromFactoryBean

AbstractAutowireCapableBeanFactory#postProcessObjectFromFactoryBean

1
2
3
4
@Override
protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
return applyBeanPostProcessorsAfterInitialization(object, beanName);
}

AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization

1
2
3
4
5
6
7
8
9
10
11
12
13
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {

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

返回getObjectForBeanInstance

bean 的依赖(@DependencyOn)和循环依赖的解决

DefaultSingletonBeanRegistry#isDependent

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) {
if (alreadySeen != null && alreadySeen.contains(beanName)) {
return false;
}
String canonicalName = canonicalName(beanName);
Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
if (dependentBeans == null) {
return false;
}
if (dependentBeans.contains(dependentBeanName)) {
return true;
}
for (String transitiveDependency : dependentBeans) {
if (alreadySeen == null) {
alreadySeen = new HashSet<>();
}
alreadySeen.add(beanName);
if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
return true;
}
}
return false;
}

getSingleton

[ObjectFactory](#ObjectFactory singletonFactory)

DefaultSingletonBeanRegistry#getSingleton

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
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
//同样的讲beanName放到 singletonsCurrentlyInCreation 中
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
// 由ObjectFactory创建完成
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
afterSingletonCreation(beanName);
}
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}

beforeSingletonCreation

DefaultSingletonBeanRegistry#beforeSingletonCreation

检查bean name 是否singletonsCurrentlyInCreationmap中了 如果是的话抛错,否则加入进入Map中

afterSingletonCreation

DefaultSingletonBeanRegistry#afterSingletonCreation

检查bean name 是否singletonsCurrentlyInCreationmap中了 如果不是的话抛错,根据bean name 对对象进行移除

addSingleton

DefaultSingletonBeanRegistry#addSingleton

1
2
3
4
5
6
7
8
9
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
//加入的时机是ObjectFactroy 触发 getObject 的时候
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}

createBean

AbstractAutowireCapableBeanFactory#createBean

这里就是ObjectFactory#getObject 调用的内容

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
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);
}
}
resolveBeforeInstantiation

AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}

一般在这个环节都是在处理各种的动态代理

//TODO

介绍一下一种RedLock 在遇到预期的Exception的时候自动删除锁的方式

  • 有一个注解@LockReleaseCondition,这个注解有两个属性

    1. 幂等锁的前缀

    2. 要响应的Exception的list。

  • BeanPostProcessor接口

    实现postProcessBeforeInitialization

    1
    2
    3
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    return bean;
    }

    根据bean找到对应的Class,检查Class 中每一个方法是否被@LockReleaseCondition注解修饰,将被修饰的方法放到List中。如果这个List不为empty。生成这个类的代理类,ProxyFactory proxyFactory = new ProxyFactory(bean);对list的方法中的method生成两个Advisor。一个实现ThrowsAdvice,检查抛出的Exception中是不是有注解中定义的Exception。如果有的然后在ReadLock中删除Key。第二个实现AfterReturningAdvice, 在方法结束的时候删除在ThreadLocal中的key,解决重入问题。

Spring 代理的部分](http://blog.andrewchen1.top/2020/08/30/spring-proxy/)

getSingleton

doCreateBean

AbstractAutowireCapableBeanFactory#doCreateBean

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {

// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 根据指定bean使用的对应策略创建实例, 比方说工厂构造函数 etc
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}

// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}

// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
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");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}

if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}

// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}

return exposedObject;
}
createBeanInstance

AbstractAutowireCapableBeanFactory#createBeanInstance

这个的arg是从doGetBean的args 参数来的 一般情况下可以忽略?

判断是通过什么方式构造这个bean 工厂/构造函数/setter?

提前曝光 循环依赖解决

addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

检查是不是需要进行曝光。是的话 创建一个ObjectFactoy 实例放到singletonFactories。这个ObjectFacotry和bean的加载 中的getSingleton方法中构建的ObjectFactory完全不是一回事情

  • addSingletonFactory

    DefaultSingletonBeanRegistry#addSingletonFactory

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(singletonFactory, "Singleton factory must not be null");
    synchronized (this.singletonObjects) {
    if (!this.singletonObjects.containsKey(beanName)) {
    this.singletonFactories.put(beanName, singletonFactory);
    this.earlySingletonObjects.remove(beanName);
    this.registeredSingletons.add(beanName);
    }
    }

  • getEarlyBeanReference

AbstractAutowireCapableBeanFactory#getEarlyBeanReference

1
2
3
4
5
6
7
8
9
10
11
12
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}

如果A和B项目相互依赖,A在populateBean的时候在BeanFactory中找B。 B不存在,也按照流程进行创建, 在populateBean的时候,getBean A,在BeanFactory中的singleonFactories找到A。触发getObejct方法。实际上会触发

AbstractAutowireCapableBeanFactory#getEarlyBeanReference这个方法

  • populateBean

    AbstractAutowireCapableBeanFactory#populateBean

    主要做的事情是

    1. 调用postProcessAfterInstantiation
    2. 根据注入类型提取依赖的bean,存入PropertyValues
    3. 应用InistantiationAwareBeanPostProcessor处理器的PostProcessPropertyValues方法。@Value和@Resource就是分别通过AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor组件的postProcessProperties方法对组建进行填充
  • initializeBean

    AbstractAutowireCapableBeanFactory#initializeBean

    1. invokeAwareMethod
    2. 触发我们在init=“”中定义的方法

ListableBeanFactory 和ApplicationContext

reflush

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
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
// 准备刷新的上下文环境
prepareRefresh();

// Tell the subclass to refresh the internal bean factory.
//初始化BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

// Prepare the bean factory for use in this context.
// 对BeanFactory进行各种功能填充
prepareBeanFactory(beanFactory);

try {
// Allows post-processing of the bean factory in context subclasses.
// 子类覆盖方法做额外的处理
postProcessBeanFactory(beanFactory);

// Invoke factory processors registered as beans in the context.
// 激活各种BeanFactory处理期
invokeBeanFactoryPostProcessors(beanFactory);

// Regis处理器ter bean processors that intercept bean creation.
// 注册拦截Bean创建的Bean
registerBeanPostProcessors(beanFactory);

// Initialize message source for this context.
// 初始化应用消息广播器
initMessageSource();
// Initialize event multicaster for this context.
//初始化应用消息广播器
initApplicationEventMulticaster();

// Initialize other special beans in specific context subclasses.
// 留给子类来初始化其他的Bean
onRefresh();

// Check for listener beans and register them.
// 在所有注册的bean中查找Listener Bean,注册到广播中
registerListeners();

// Instantiate all remaining (non-lazy-init) singletons.
// 初始化剩下的单实例
finishBeanFactoryInitialization(beanFactory);

// Last step: publish corresponding event.
// 完成刷新过程,通知生命周期处理器
finishRefresh();
}

prepareRefresh

步骤没有做什么

obtainFreshBeanFactory

AbstractApplicationContext#obtainFreshBeanFactory

1
2
3
4
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}

AbstractRefreshableApplicationContext#refreshBeanFactory

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Override
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
// 定制BeanFactory,设置相关属性
customizeBeanFactory(beanFactory);
// 初始化 DodumentReader, 并进行XML文件读取和解析
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}

回到reflush

prepareBeanFactory

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
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
// 设置classLoader
beanFactory.setBeanClassLoader(getClassLoader());
// 设置beanFactory的语言表达式
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

// Configure the bean factory with context callbacks.
// 增加BeanPostProcessor
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.
// 增加@AspectJ的支持
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.
// 添加默认的Bean
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());
}
}

增加对SPEL 语言的支持

AbstractAutowireCapableBeanFactory#autowireBean

AbstractAutowireCapableBeanFactory#configureBean

AbstractAutowireCapableBeanFactory#autowire

AbstractAutowireCapableBeanFactory#autowireBeanProperties

AbstractAutowireCapableBeanFactory#doCreateBean

其中doCreateBean 是在BeanFactory会调用到的函数

中都会调用

AbstractAutowireCapableBeanFactor#populateBean

然后调用

AbstractAutowireCapableBeanFactor#applyPropertyValues
在这个方法中会生成

BeanDefinitionValueResolver

然后会调用

BeanDefinitionValueResolver#resolveValueIfNecessary

然后会调用

BeanDefinitionValueResolver#doEvaluate

调用

AbstractBeanFactory#evaluateBeanDefinitionString

就是在这个地方实现SPEL的解析

回到prepareBeanFactory

增加对属性编辑器的支持

1
2
3
4
@Data
public class UserManager {
private Date dateValue;
}

然后我们尝试构造这个Bean

1
2
3
4
5
<bean id="userManager" class="com.test.UserManager">
<property name="dateValue">
<value>2013-01-01</value>
</property>
</bean>

事实上是会失败的

方法1
1
2
3
4
5
6
7
8
9
10
11
@Slf4j
public class DatePropertyEditor extends PropertyEditorSupport {
private static final DateTimeFormatter DATETIMEFORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");

@Override
public void setAsText(String text) throws java.lang.IllegalArgumentException {
log.info("args {}", text);
Date date = Date.from(LocalDateTime.from(DATETIMEFORMATTER.parse(text)).atZone(ZoneId.systemDefault()).toInstant());
this.setValue(date);
}
}

然后在spring中进行注册

1
2
3
4
5
6
7
8
9
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entity key="java.util.Date">
<bean class=" com.example.demo.DatePropertyEditor"/>
</entity>
</map>
</property>
</bean>

这样的配置,当Spring在注入bean的属性时,一旦遇到了java.util.Date类型的属性会自动调用自定义的DatePropertyEditor

方法2
1
2
3
4
5
6
public class DatePropertyEditorRegistrar implements PropertyEditorRegistrar {
@Override
public void registerCustomEditors(PropertyEditorRegistry registry) {
registry.registerCustomEditor(Date.class, new DatePropertyEditor());
}
}
1
2
3
4
5
6
7
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="propertyEditorRegistrars">
<list>
<bean class="com.example.demo.DatePropertyEditorRegistrar"/>
</list>
</property>
</bean>
在什么时候触发的

AbstractAutowireCapableBeanFactory#doCreateBean

调用

AbstractAutowireCapableBeanFactory#createBeanInstance

调用

AbstractAutowireCapableBeanFactory#instantiateBean

调用

AbstractBeanFactory#initBeanWrapper

调用

AbstractBeanFactory#registerCustomEditors

调用

PropertyEditorRegistrar#registerCustomEditors

回到prepareBeanFactory

添加 ApplicationContextAwareProcessor 处理器 设置EnvironmentAware等的信息

ApplicationContextAwareProcessor#postProcessBeforeInitialization

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 Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
return bean;
}

AccessControlContext acc = null;

if (System.getSecurityManager() != null) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}

if (acc != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareInterfaces(bean);
return null;
}, acc);
}
else {
invokeAwareInterfaces(bean);
}

return bean;
}

ApplicationContextAwareProcessor#invokeAwareInterfaces

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}

回到prepareBeanFactory

设置了依赖功能可忽略的接口

*Aware 需要在Spring 做bean 依赖注入的时候忽略他们。因为他们不是普通的Bean,只是要实现和FactoryBean一样只是为了实现特定目的的Bean,就不要生成Bean,放到singletonObjects 里面了

1
2
3
4
5
6
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

调用顺序

调用的顺序为

AbstractAutowireCapableBeanFactory#doCreateBean

调用

AbstractAutowireCapableBeanFactory#populateBean

调用

AbstractAutowireCapableBeanFactory#autowireByType

or

AbstractAutowireCapableBeanFactory#autowireByName

调用

AbstractAutowireCapableBeanFactory#unsatisfiedNonSimpleProperties

调用

AbstractAutowireCapableBeanFactory#isExcludedFromDependencyCheck

回到prepareBeanFactory

注册固定依赖的属性

1
2
3
4
5
6
7
// 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);

调用的顺序为

AbstractAutowireCapableBeanFactory#doCreateBean

调用

AbstractAutowireCapableBeanFactory#populateBean

调用

AbstractAutowireCapableBeanFactory#autowireByType

调用

DefaultListableBeanFactory#resolveDependency

调用

DefaultListableBeanFactory#doResolveDependency

调用

DefaultListableBeanFactory#findAutowireCandidates

回到prepareBeanFactory

增加AspectJ的支持

将相关环境变量及属性注册以单例模式组册

回到reflush

invokeBeanFactoryPostProcessors

For example

org.springframework.beans.factory.config#PropertyOverrideConfigurer

这个类的作用是

回到reflush

registerBeanPostProcessors

回到reflush

-p09-】

构造数据抽象

  • 复合数据
  • 闭包
  • 符号表达式

数据抽象导引

假设make-rat 能使分数最简化

假设 number 能获得分子,denom 能获得分母

  • 加法
1
2
3
4
5
(define (add-rat x y) 
(make-rat (+ (*(number x) (denom y))
(* (denom x) (number y)))
(* (denom x) (denom y)))
)
  • 减法
1
2
3
4
5
6
(define (sub-rat x y)
(make-rat (- (*(number x) (denom y))
(*(denom x) (number x))
)
(* (denom x) (denom y)))
)
  • 乘法
1
2
3
4
(define (mul-rat x y)
(make-rat (* (number x) (number y)
(* (denom x) (denom y)))
)
  • 除法
1
2
3
4
(define (div-rat x y)
(make-rat (* (number x) (denom y))
(* (denom y) (number x)))
)
  • 判断是否相等
1
2
3
4
(define (equal-rat x y) 
(= (* (number x) (denom y)
(* (denom y) (number x)))
)
  • 构造函数
1
2
3
(define x (cons 1 2))
(car x)
(cdr x)

得到的结果分别是 1 和 2

1
2
3
4
5
6
7
(define (make-rat n d)
(let (
(g (gcd n d))
)
(cons (/ n g) (/ d g))
)
)

而 gdc 最大公约数,之前我们介绍过, 可以通过中国余数的方式获得

1
2
3
4
(define (gcd n d)
(if (= 0 d) (n)
(gcd (d (reminder n d))
)

层次性数据和闭包性质

序对为我们提供一种用于构造复合数据的基本“粘结剂”。我们还可以通过它去组合起序对。

1
2
3
(cons (cons 1 2) (cons 1 2))

(cons (cons 1 (cons 2 3)) 4)

(⚠️ 上面的方式不是序列。)

我们可以建立元素本身也是序对的序对,这就是表结构得以作为一种表示工具的根本基础。我们把这种能力称为cons的闭包。

术语 闭包 来自于抽象代数。在抽象代数里,一集元素称为在某个元算(操作)之下封闭。如果将该运算应用于这一集合中的元素,产生出的仍是该集合里的元素。

序列的表示

利用序对可以构造出的一类有用结构是序列。 和Java的数据结构比较对应数据结构是链表

1
2
3
4
(cons 1 
(cons 2
(cons 3
(cons 4 nil))))

通过嵌套的cons形成的这样一个序对的序列称为一个, 它和上面的程序等价

1
(list 1 2 3 4)

我们将car看作选取表的第一项的操作,将cdr看作选取表中除去第一项之后剩下的所有项形成的子表

比方说我们想得到表的第n项

1
2
3
(define (list-ref item)
(if (= 0 item) (car item)
(list-ref (cdr item) (- item 1))))

比方说append

1
2
3
4
5
6
(define (append list1 list2)
(if (= nil list1)
(list2)
(cons (car list1) (append((cdr list1) list2)))
)
)

首先找到list1的最后一个元素。 把list1最后一个元素的next设置为list2. 依次递归。其中过程中的list1和参数的list1不等价。

对表的映射

$(1\ 2 \ 3) * 3 = (3 \ 6 \ 9)$

1
2
3
4
5
6
7
8
9
(define (scale-list items factor)
(if
( = nil items)
(nil)
(
(cons (* (car items) factor) (scale-list (crd items) factor))
)
)
)

我们将其中的公共模式表述成一个高阶过程,这个高阶过程我们称之为map。返回将这一个过程应用于表中各个元素得到的结果形成的表

通式为

1
2
3
4
5
6
7
8
9
(define (map proc items)
(if (= nil items)
(nil)
(cons
(proc (car items))
(map proc (crd items))
)
)
)

有了这个公式我们可以简化上述集合的乘法

1
2
3
4
5
6
(define (scale-list items factor)
(map (lambda (x)
(* x factors)
)
items)
)

层次性结构

1
(cons (list 1 2) (list 3 4))

我们把这种数据结构称之为

1
2
3
4
5
6
7
8
9
10
(define (count-leaves x)
(cond
((null? x) 0)
((pair? x)
(+ (count-leaves (car x))
(count-leaves (cdr x))
))
(else 1)
)
)

其中pair? 的作用是检查是不是序对

对树的映射

1
2
3
4
5
6
7
8
9
10
11
(define (scale-tree tree factor)
(map (lambda (sub-tree)
(if
(pair? sub-tree)
(scale-tree sub-tree factor)
(* factor sub-tree)
)
)
tree
)
)

序列作为一种约定的界面

以一棵树为参数,求值为奇数叶子的平方和

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(define (sum-odd-squares tree)
(map (lambda (sub-tree)
(cond ((null? sub-tree)
0
)
(if (pair? sub-tree)
(+ (sum-odd-squares (car sub-tree))
(sum-odd-squares (cdr sub-tree))
)
(if (= 1 (reminder sub-tree 2))
(square sub-tree)
)
)
)
tree)
)

构造偶数的斐波那契数列的表

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
(define (fibs-iter n_1 n_2 cur N total) 
(if (= cur N)
total
(fibs-iter (+ n_1 n_2) n_1 (+ cur 1) N (+ n_1 total )))
)

(define (fibs N)
(fibs-iter 1 0 0 N 0)
)

(define (even-fibs n)
( (lambda (k)
(> k n)
nil
(if (even? (fibs n))
(cons (fibs n)
)
)
)
(lambda
(sub-list k)
(if (
(> k n)
nil
(if
(even? (fibs n))
(cons (fibs n) sub-list)
)
(
(< k n)
()
)

)
)
)
)

程序设计的基本元素

  1. 基本表达式

    用于表示语言所关心的最简单的个体

  2. 组合的方法

    通过它们可以从比较简单的东西出发构造出复合的元素

  3. 抽象的方法

    通过它们可以为复合对象命名,并将它们当作单去操作

表达式

(* 1 2 3 4)

像上面这样的表达式称为组合式,其构成方式就是用一对括号括起一些表达式,形成一个 用于表示一个过程应用。在表最左边的元素被称为运算符,其他元素都称为运算对象。

命名和环境

(define size 2)

组合式的求值

( * (+ 2 (* 4 6) (+ 3 5 7))

复合过程

  • 数和算数计算是基本的数据和过程
  • 组合式的嵌套提供了一种组织起多个操作的方法
  • 定义是一种受限的抽象手段,它为名字关联相相应的值

(define ( ) )

过程应用的代换模型

1
2
3
4
5
6
7
8
9
(define (f a)
(define (square n)
(* n n)
)
(define (sum-of-squares a)
(+ (square (+ 1 a)) (square(+ 2 a)))
)
(sum-of-squares a)
)

要得到结果先要把式子替换成sum-of-squares的定义,进一步的要替换成square的定义。这样的计算过程被称为代换模型

应用序和正则序

这种“完全展开而后归约”的求值模式被称为正则序求值,对于上面的f 函数来说就是 变成

1
(+ (* (+ 5 1) (+ 5 1)) (* (* 5 2) (* 5 2)))

然后进行规约

与之相对应的是现在解释器里实际使用的“先求值参数而后应用”的方式,它称为应用序求值

条件表达式和谓词

(cond

​ ( )

​ ( )

(if () () () )

谓词中允许中使用的词

  • (and
  • (or )
  • (not )

实例:采用牛顿法求平方根

$ \frac { {x} / {y^2} + 2y} {3}$

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
(define (square x)
(x * x)
)
(define (cue x)
(x * x *x)
)
(define good_guess(this_guess last_guess)
(< (abs (- this_guess last_guess)) 0.0001)
)
(define get_this_time_guess(last_guess x)
(/ (+ (/ x square(last_guess)) (* 2 last_guess)) 3)
)
(define cue_root_inter(last_guess x)
(if (good_guess (get_this_time_guess last_guess x) last_guess)
(get_this_time_guess last_guess x)
(cue_root_inter (get_this_time_guess last_guess x) x)
)
)
)
(define (cue_root x)
cue_root_inter(1.0 x)
)

过程作为黑箱抽象

与其说cue_root 是一个过程,还不如说它一个过程的的抽象

局部名

过程的形式参数在过程体系里扮演着一种非常特殊的角色,在这里,形式参数的具体名字是什么,其实完全没有关系。这样的名字被称为约束变量。 如果一个变量不是被约束的,我们称它为自由的。

在good_guess中this_guess和last_guess是约束的,< abs 是自由的。

内部定义和块结构

目前的程序是几个相互分离的过程组成,如果统一到同一个方法块中。 这种嵌套的定义称为块结构

过程与它们所产生的计算

我们现在已经考虑了程序设计中的一些要素

使用许多基本的算数操作

对这种操作进行组合

定义各种复合过程

线性的递归和迭代

1.

1
2
3
4
5
(define (factorial n)
if (= n 1)
(1)
(* n factorial(- n 1)))

2.

1
2
3
4
5
6
7
8
(define (factorial n)
(define (factorial-iter product current_count max_count)
(if(= current max_count)
(* product current)
(factorial-iter (* product current) (+ current 1) max_count)
)
)
)

在第1个中。代换模型解释出一个推迟进行的操作所形成的链条。收缩阶段表现为这些运算的实际进行。称为*递归计算过程*,它的长度随着n值而线性增长,这样的计算过程为一个线性递归过程

在第2个中,没有任何增长或者收缩。在我们需要保存轨迹里,所有的东西就是变量product、current_count和max_count的值。我们称这种过程为一个迭代计算过程。迭代计算过程就是那种其状态可以用固定数据的状态变量描述的计算过程

从另一个角度来看这两个过程之间的对比。在迭代的情况里,在计算过程中的任何一点,那几个程序变量都提供了有关计算状态的完整表述。如果我们令上述计算在某两个步骤之间停下来,想要重新唤醒这一计算,只需要为解释器提供有关这三个变量的值。

对于递归计算而言,这里还存在着另外的一些隐含信息,它们由解释器维持着。

注意

这不表示第二种方式不是递归。 只是解释器采用优化 把它优化成类似于while等的方式。我们称之为尾递归。

树形递归

斐波那契数列

  1. 递归方式调用
1
2
3
4
5
6
(define (fib n) 
(cond ((= n 1) (1))
((= n 2) (1))
((> n 2) (+ fib((- n 1)) fib((- n 2))))
)
)
  1. 迭代的方式调用
1
2
3
4
5
6
7
8
9
10
(define (fib n)
(fib-iter(n 3 1 1))
)
(define (fib-iter N cur less1 less2)
(cond ((= 1 N) 1)
((= 2 N) 1)
((= cur N) (less1))
(else (fib-iter N (+ cur 1) (+ less1 less2) less1)
)
)

换零钱方式

这个会比较复杂一点。就是用递归的方法进行计算有多少种方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
(define (first-denomination kinds-of-conions)
(cond ((= kinds-of-conins 1) 1)
((= kinds-of-conins 2) 5)
((= kinds-of-conins 3) 10)
((= kinds-of-conins 4) 25)
((= kinds-of-conins 5) 50)
)
)
(define (count-change amount)
(cc amount 5))

(define (cc amount kinds-of-conions)
(cond ((= 0 amount) 1)
((or (< amount 0) (= kinds-of-conions 0)) 0)
(else ( (+ (cc amount (- kinds-of-conions 1))
(cc (- amount
(first-denomination kinds-of-conions))
)
)
)
)
)
)

下面是比较好理解的Java的方式

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
public class Main {
public static void main(String[] args) {
int[] arrange = {0, 0, 0, 0, 0};
cal(arrange, 50);
}

public static void cal(int[] arrange, int money) {
if (money == 0) {
System.out.println("50 cent " + arrange[0] + " 25 cent " + arrange[1] + " 10 cent " + arrange[2] + " 5 cent " + arrange[3] + " 1 cent" + arrange[4]);
return;
}
if (money >= 50) {
arrange[0] += 1;
cal(arrange, money - 50);
arrange[0] -= 1;
}
if (money >= 25) {
arrange[1] += 1;
cal (arrange, money - 25);
arrange[1] -= 1;
}
if (money >= 10) {
arrange[2] += 1;
cal(arrange, money - 10);
arrange[2] -= 1;
}
if (money >= 5) {
arrange[3] += 1;
cal(arrange, money -5);
arrange[3] -= 1;
}
if (money >= 1) {
arrange[4] += 1;
cal(arrange, money - 1);
arrange[4] -= 1;
}
}
}

练习 1.11

1
2
3
4
5
6
7
8
9
10
(define (fun-iter n cur a b c)
(cond (((= n 1) 1)
((= n 2) 2)
((= n 3) 3)
((= n cur) a)
(else (fun-iter n (+ cur 1) (+ (* a 3) (* b 2) c) a b)
)
(define (func n)
(fun-iter n 3 3 2 1)
)

练习 1.12

1
2
3
4
5
6
(define (pascal row col)
cond ( (> col row) (error "unvalid col value")
((or (= col 0) (= col row)) 1)
(+ pascal((- row 1) col) pascal((- row 1) (+ col 1)))
)
)

这样的效率会很慢

由帕斯卡三角形(杨辉三角形)的公式可得 ${row \choose col}= \frac {row!} {col!(row−col)!}$

杨辉三角就是 $(x+1)^n$ 的系数的值

单就3项而言 $\frac {n(n-1)} {2!}$ => $ \frac {n(n-1)(n-2)(n-3)…} {(n-k)!k!}$ => 这个值等价于 $\frac {n!} {k! (n-k)!}$

在二项式的展开中 除了第一项和最后一项 每一项中都会有n,根据素数的定义,素数的因数只有1和它本身,所以后在二项式展开的2到n-1 项中的n都不会被整除,会被保留。

所以在n是素数的情况下从第2项到n-1项的值都是n的倍数

所以检查素数的方法

求$(x+1)^n$展开式从第2到n-1项

1
2
3
4
5
6
7
8
9
(define (factorial n)
(fact-iter 1 1 n))
(define (fact-iter p b e)
(if (> b e)
p
(fact-iter (* p b)(+ b 1) e))
)
(define (pascal row col)
(/ (factorial row) (* (factorial col) (factorial (- row col)))

更相减损术

1
2
3
(define (gcb a b)
(if (= 0 b) a ( gcb b (remainder a b) )
)

实例 1.2.6 素数检测

1
2
3
4
5
6
7
8
9
10
(define (devides? a b) 
(= (remainder a b) 0)
(define (smallest-divisor n)
(find-divisor n 2))

(define (find-devisor n b)
(conds ((> (square b) n)) n)
((devides? n b) b)
(else (find-deversior n (+ b 1))
)

费马小定理

先说结论当n为素数的时候 $(a^n-a)mod(n) = 0$ 进一步的

$a^nmod(n) = a$

=>

$a^{n-1}mod(n)=1$

人们通常把这样的式子写作

$a^{n-1} \equiv 1 (mod \ n)$

证明

  1. 首先我们根据二项式定理能证明,当n为素数的时候 $((a + 1) ^ n - 1 - a^n )mod (n) = 0$
  2. 将费马小定理和二项式定理进行加和 $(a + 1) ^ n - 1 - a^n + a^n-a$
  3. 整理一下 得到 $((a+1)^n - (a+1))$
  4. 发现整理后的结果是 费马小定理的 n + 1 项。 已知二项式定理成立, 其结果能被n整除,若费马小定理的n项成立,即结果能被n整除,通过上式可知, 费马小定理的第 n+1 项必然成立
  5. 那么通过数学归纳法,我们去求当a为的0时候,那么 $(0^n-0)$ 的值。 0能被任何素数整除
  6. 所以费马小定理成立

注意 费马小定理是证明素数的充分不必要条件,比方说561 = 17 * 3 * 11. 但是 561 复合费马小定理的公式

换个表述方式我们定义$\phi(n)$ 为1~n中和n互质的数,我们可以得到 $a^{\phi(n)} = 1 (mod \ n)$,这个就是欧拉函数

欧拉函数

$a^{\phi(n)} = 1 (mod \ n)$

$\phi(n)$表示在1~n中和n互质的数

几个常用的定理

  1. 当n和m互质

$\phi(nm) = \phi(n) * \phi(m)$

  1. 当p为质数

    $\phi(p) = p - 1$

  2. 当n为奇数的时候

    $\phi(2 * n) = \phi(n)$

  3. 当 $n = p ^k$的时候

    $\phi(n) = p^k * (1-\frac {1} {p}) = p^k - p^{k-1}$

其他性质

题目

求$3^{83}$最后两位的值

​ 根据欧拉公式$a^{\phi(n)} = 1 (mod \ n)$

$\phi(100) = \phi(4)\phi(25)=(2^2-2)*(5^2-5)=40$

$3^{83} = 3^3 * 3^{80} = 3^3 * (3 ^{\phi(100)})^2\equiv 3^3 = 27$

凶残小姐姐的知乎介绍

用高阶函数抽象

过程作为参数

例子1

1
2
3
4
5
(define (sum-cubes a b)
(if ((a > b) 0)
(+ (cube a) (sum-cubes (+ 1 a) b))
)
)

例子2

$$\sum_{n 0\to\infty }{\frac{1}{(1+4n)(3+4n)}} = {\frac {\pi} {8}}$$

1
2
3
4
5
(define (pi-sum a b)
(if ( (> a b) 0)
(else (+(/ 1 (+ 1 (* 4 n)))))
)
)

我们可以填充下面模板中的各空位,产生出上面的各个过程:

1
2
3
4
5
6
7
(define (<name> a b)
(if (
((> a b) 0)
(+ (<term> a)
(<name> (<next> a) b)
)
)

转换一下

1
2
3
4
5
6
7
8
9
(define (sum term a next b)
(if ((> a b) 0)
(else (+ (term a)
(sum term (next a) next b)))

)
(define (inc n) (+ n 1))
(define (sum-cube a b)
(sum cube a inc b))

相当于把过程作为参数传入

然而,即使在数值计算过程中,如果将过程限制为只能以数作为参数,那么会严重的限制我们抽象的能力。经常有一些同样的程序设计模式能用于若干不同的过程,为了把这种模式描述为响应的概念吗,我们就需要构造出这样的过程,让他们以过程为参数。这类能操作过程的过程称为高阶过程

用lambda构造过程

如果不需要显示定义pi-term和pi-next,而是有一种方法直接刻画过程。我们可以通过引入一种lamdba特殊形式完成这种描述。

定义名称很麻烦我们利用lambda, 按照如下方式写出所需的东西

(lambda (x) (+ x 4))

(lambda表达式可用作组合式的运算符。 lambda表达式可做运算符

1
((lambda (x y z) (+ x y (square z))) 1 2 3)

逻辑的过程是

我们通过过程名称调用过程 -> 将过程作为参数传入 -> 将lambda (匿名函数) 作为参数传入

用let创建局部变量

$f(x,y) = x(1+xy)^2+y(1-y) + (1+xy)(1-y)$

1
2
3
4
5
6
7
8
9
(define (f x y)
(define (f-helper a b)
(+ (* x square a) (* y b) (* a b))
)
(f-helper
(+ 1 (* x y))
(- 1 y)
)
)

如果使用lambda的话

1
2
3
4
5
6
7
8
9
(define (f x y)
((lambda (a b)
(+ (* x square a)
(* y b)
(* a b)))
(+ 1 (* x y))
(- 1 y)
)
)

如果使用let的话

1
2
3
4
5
6
7
8
9
10
(define (f x y)
(let (
(a (+ 1 (* x y)))
(b (- 1 y)))
(+ (x (square x))
(* y b)
(* a b)
)
)
)

let 表达式只是作为基础lambda表达式的语法外衣罢了

方法

3.1 结构

3.1.1 执行模型

每个线程都有自己的执行栈,栈由栈帧组成。每个帧表示一个方法调用。每次调用一个方法时,会将一个新栈帧push入当前线程的执行栈。当方法返回时,会讲这个帧从执行栈中弹出,执行过程在发出调用的方法中继续进行每一帧包括

  • 操作数栈
  • 局部变量表
  • 动态链接(DL)
  • 方法返回

局部变量表与操作数栈大小取决于方法的代码。

在创建一个帧时会将其初始化,提供一个空栈,并用目标对象this(非静态方法),以及该方法的参数来初始化局部变量。比如调用a.equals(b)将创建一个帧,它有一个空栈,前两个局部变量被初始化为a和b

3.1.2 字节代码指令

字节代码指令由一个表示该指令的操作码和固定数目的参数组成

  • 操作码 是由一个无符号字节值,由助记符号标识。
  • 参数时静态值,确定了精确的指令行为

字节代码指令可以分为两类

  1. 一小组指令。设计用在局部变量表和操作数栈之间传送值
  2. 仅用于操作数栈:从栈中弹出一些值,根据这些值计算一个结果,并将它压回栈中

ILOAD,LLOAD,FLOAD,DLOAD,ALOAD。 他们的参数必须是读取的局部变量的索引i。

  • ILOAD 加载 boolean、byte、char、short、int局部变量
  • LLoad、FLoad、DLoad 分别用于记载long,float,double的值
  • ALoad 用于加载任意非基元值即对象和数组

ISTORE, LSTORE,FSTORE, DSTORE, ASTORE 从操作数栈中弹出一个值,并且将它存储在由索引i指定的局部变量中

xLoad和xStore指令被赋入了类型。确保不会执行非法转换。实际上,将一个值存储在局部变量中,然后再以不同的类型加载它是非法的。比方说ISTORE 1ALOAD1 序列是非法的。但是向一个局部变量中存储一个值,而这个值的类型不同于该局部变量中存储的当前值,却是完全合法的。

  • POP弹出栈顶部的值,DUP 压入顶部,SWAP弹出两个值,并且按逆序压入他们

  • 常量

    这些指令在操作数栈压入一个常量值:ACONST_NULL 压入null,ICONST_0 压入int0, FCONST_0 压入0f,DCONST_0压入0d,BIPUSH b 压入字节值b,SIPUSH s 压入short值 s,LDC 压入任意int、float、long、double、String或者class 常量cst

  • 算数与逻辑

    这些指令从操作数栈弹出数值,合并他们,并将结果压入栈中。他们没有任何参数。xADD,xSUB,xMUL,xDIV和xREM。

  • 类型变换

    这些指令从栈中弹出一个值,将其转换为另一种类型,并将结果压入栈中。他们对应Java中的类型转换表达式。I2F,F2D,L2D等将数值由一种数值类型转换为另一种类型。CHECKCAST t将一个引用值类型转换为类型t

  • 对象

    这些指令用于创建对象、锁定他们、检测他们的类型,等等。 NEW type 指令将一个type类型的新对象压入栈中

  • 字段

    这些指令读或者写一个字段的值。GETFIELD ower name desc 弹出一个对象引用,并将name字段中的值压入栈中。PUTFIELD owner name desc 弹出一个值和一个对象引用,并且将这个值存储在它的name字段中。在这两种情况下,该对象都必须是owner类型,它的字段必须是desc类型。GETSTATIC和PUTSTATIC是类似的指令

  • 方法

    这些指令调用一个方法或构造器。它们弹出值的个数等于其方法参数个数 + 1(用于目标对象),并压回方法调用的结果。 INVOKEVIRTUREAL owner name des调用在类owner中定义的name方法,其方法描述符为desc。INVOKESTATIC 用于静态方法,INVOKESPECIAL用于私有方法和构造器。INVOKDYNAMIC用于动态方法调用机制

  • 数组

    这些指令用于读写数组中的值。xALOAD指令弹出一个索引和一个数组,并压入此索引处数组元素的值。xASTORE指令弹出一个值,一个索引和一个数组,并将这个值存入在该数组的这一索引处。x可以为I(int)、L(long)、F(float)、D(double)、A(other)、B(byte)、C(char)、S(short)

  • 跳转

    这些指令无条件的或者在某一条件为真的时候跳转到任意指令。它们用于编译if、for、do、while、break、continue指令。IFEQ label 从栈中弹出一个int值,如果这个值是0,跳转到label指定的指令处。还有其他的指令IFNE、IFGE、TABLESWITCH、LOOKUPSWITCH 对应switch 指令

  • 返回

    RETURN用于返回void方法,xRETURN用于其他方法

3.1.3 举例说明

1
2
3
4
5
6
7
8
9
10
11
public class Bean {
private int f;

public int getF() {
return f;
}

public void setF(int f) {
this.f = f;
}
}

3.1.3.1 getter

getter的字节码为

1
2
3
ALOAD 0
GETFIELD pkg/Bean f I
IRETURN

读取局部变量0,(局部变量0在为这个方法调用创建帧期间被初始化为this),并且将这个值压入操作数栈中。

从操作数栈中弹出这个值,并且将这个对象的f字段压入栈中

从栈中弹出这个值,返回给调用者

3.1.3.2 setter

setter方法的字节码

1
2
3
4
ALOAD 0
ILOAD 1
SETFIELD pkg/Bean f I
RETURN

读取局部变量0,(局部变量0在为这个方法调用创建帧期间被初始化为this),并且将这个值压入操作数栈中。

压入局部变量1

弹出这两个值,并将int值存储在被引用对象的f字段中。

销毁当前执行帧,并返回调用者。

3.1.3.3 contractor

bean类有一个默认的构造函数,在没有定义的情况下是由编译器生成的。

1
2
3
Bean() {
super();
}

构造函数

1
2
3
ALOAD 1
INVOKESPECIAL java/lang/Object <init> ()V
RETURN

读取局部变量0,(局部变量0在为这个方法调用创建帧期间被初始化为this),并且将这个值压入操作数栈中。

调用Object对象中定义的<init>方法

3.1.3.4 复杂的使用

1
2
3
4
5
6
7
public void checkAndSetF(int f) {
if (f >= 0) {
this.f = f;
} else {
throw new IllegalArgumentException();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
ILOAD 1
IFLT label
ALOAD 0
ILOAD 1
PUTFIELD pkg/Bean f I
GOTO end
label:
NEW java/lang/IllegalArgumentException
DUP
INVOKESPECIAL java/lang/IllegalArgumentException <init>()V
ATHROW
end:
RETURN

3.1.3.5 异常处理器

1
2
3
4
5
6
7
public static void sleep(long d) {
try {
Thread.sleep(d);
} catch (Exception e) {
e.printStackTrace();
}
}
1
2
3
4
5
6
7
8
TRYCATCHBLOCK try catch catch java/lang/InterrutedExcetion
try:
LLOAD 0
INVOKESTATIC java/lang/Thread sleep(J)V
RETURN
catch:
INVOKEVIRTUAL java/lang/InterruptedException printStackTrace ()V
RETURN

TRYCATCHBLOCK行制定了一个异常处理器, 覆盖了try和catch标记之间的范围,有一个开始于catch标记的处理器,用于处理一些异常,这些异常是InterruptedException的子类。如果在try和catch之间抛出了一个异常,栈将被清空,异常被压入这个空栈中,执行过程在catch中继续。

3.1.3.6 帧

除了字节码指令外,Java6或者更高的编译类中还包括一组栈映射帧,用于加快Java虚拟机中类验证过程的速度。它给出了就要执行某一特定字节码指令之前,每个局部变量槽和每个操作数栈槽总包含的值的类型

为节省空间,已编译方法中没有为每个指令包含一个帧 它仅为那些应对跳转目标或者异常处理器的指令,或者跟在无条件跳转指令之后的指令创建帧。

在checkAndSetF 方法的情景中。仅存储两个帧 一个是用于NEW指令,另一个用于RETURN指令。因为它是GOTO指令的目标,还因为它跟在无条件跳转ATHROW指令后。

3.2 接口和组件

用于生成和转换已编译方法的ASM api 是基于MethodVisitor抽象类的。它由ClassVisitor的visitMethod返回。这些方法必须按照以下顺序调用

visitAnntationDefault?

(visitAnnotation | visitParameterAnnotation | visitAttribute )*

(visitCode

(visitTryCatchBlock | vistLabel | visitFrame | visitXxxInsn | visitLocalVariable | visitLineNumber) *

visitMaxs)?

visitEnd

2.1 类的结构

2.1.1 已编译类的整体结构

内容 子内容
修饰符、名字、超类、接口
常量池:数值、字符串、类型常量
源文件名(可选)
封装的类引用
注释*
属性*
内部类* 名称
字段* 修饰符、名字、类型
注释
属性
方法* 修饰符、名字、返回类型、参数类型
注释
属性
编译后的代码

* 表示0个到多个

2.1.2 类型描述符

Java类型 类型表述符
boolean Z
char C
byte B
short S
int I
float F
long J
Double D
Object Ljava/lang/Object;
int[] [I
Object[][] [[Ljava/lang/Object;

2.1.3 类型描述符

源文件中的方法声明 方法描述符
Void main (int i, float f) (IF)V
int m(Object o) (Ljava.lang.Object;)I
int[] m (int i, String s) (ILjava/lang/String;)I[
Object m(int[] i) ([I)Ljava/lang/Object;

2.2 接口和组件

2.2.1 介绍

ClassVistor 就是就是个模板 我们对类的处理都通过这个模板生成的类来进行

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
public abstract class ClassVisitor {
public ClassVistor(int api);
public ClassVistor(int api, ClassVistor cv);
/**
* verison 版本信息
* access 权限信息
* name 类的名称
* signature 泛化
* superName 父类信息
* interface 接口信息
*/
public void visit(int version, int access, String name, String signature, String superName, String[] interface);

public void visitSource(String source, String debug);

public void visitOuterClass(String ower, String name, String desc);

AnnotationVisitor visitAnnotation(String desc, Boolean visible);

public void visitAttribute(Attribute attr);

public void visitInnerClass(String name, String outerName, String innerName, int access);

public FieldVisitor visitField(int access, String name, String desc, String signature, Object value);

public MethodVisitor visitorMethod(int access, String name, String desc, String signature, String[] exceptions);

void visitEnd();
}

在上面的类中返回了 AnnotationVisitor, FieldVisitor, MethodVisitor.

1
2
3
4
5
6
7
public abstract class FieldVisitor {
public FieldVisitor(int api);
public FieldVisitor(int api, FieldVisitor fv);
public AnnotationVisitor visitorAnnotation(String desc, boolean visible);
public void visitAttribute(Attribute attr);
public void visitEnd();
}

ClassVisitor 类的方法必须按照以下的顺序进行调用

visit visitSourcce? visitOuterClass? (visitAnnotation | visitAttribute)* (visitInnerClass | visitField | visitMethod) * visitEnd

ASM提供了三个基于ClassVisitor API的核心组件,用于变化和生成类

  • ClassReader *分析以字节数组形式给出的已编译类,并针对其accept方法参数中传送的ClassVisitor实例, 调用相应的visit方法。这个类可以看作是一个时间生成器。
  • ClassWriter 是ClassVisitor抽象类的一个子类,它直接以二进行形式生成编译后的类。
  • ClassVisitor 类将它收到的所有方法调用都委托为另一个ClassVistor类。可以看作是事件筛选器。

2.2.2 分析类

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
ClassReader classReader = new ClassReader("java.lang.Runnable");
classReader.accept(new ClassVisitor(ASM4) {
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interface) {
System.out.println(name + "extends" + superName + "{ ");
}
@Override
public void visitSource(String source, String debug) {

}
@Override
public void visitOuterClass(String ower, String name, String desc) {

}
@Override
AnnotationVisitor visitAnnotation(String desc, Boolean visible) {
return null;
}
@Override
public void visitAttribute(Attribute attr) {

}
@Override
public void visitInnerClass(String name, String outerName, String innerName, int access) {

}
@Override
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
System.out.println(" " + desc + " " + name);
return null;
}
@Override
public MethodVisitor visitorMethod(int access, String name, String desc, String signature, String[] exceptions) {
System.out.println(" " + name + desc);
}

void visitEnd() {
Sysgtem.out.println("}");
}
}, 0);

获得的结果是

java/lang/Runnable extends java/lang/Object {

​ run()V

}

2.2.3 生成类

如果我们想生成类

1
2
3
4
5
6
7
package pkg;
public interface Comparable extends Mesurable {
int LESS = -1;
int EQUAL = 0;
int GRATER = 1;
int compareTo(Object o);
}

我们可以对ClassVisitor进行6次方法调用来生成它:

1
2
3
4
5
6
7
8
9
10
11
ClassWriter cw = new ClassWriter();
cw.visitor(V1_5, ACC_PUBLIC + ACC_ABSTRACT + ACC_INTERFACE, "pkg/Comparable", null, "java/lang/Object");
cw.visitField(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, "LESS", "I", null, new Integer(-1)).visitEnd();
cw.visitField(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, "EQUAL", "I", null, new Integer(0)).visitEnd();
cw.visitField(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, "GRATER", "I", null, new Integer(1)).visitEnd();

cw.visitField(ACC_PUBLIC + ACC_ABSTRACT, "compareTo", "(Ljava/lang/Object;)I", null, null).visitEnd();

cw.visitEnd();

byte[] b = cw.toByteArray();

产生的中间码可以被clasLoader

new ClassLoad().defineClass(“pkg.Comparable”, b, 0, b.length);

或者

1
2
3
4
5
6
7
8
9
10
11
12
class StubClassLoader extend ClassLoader {
@Override
protected Class findClass(BeanDenefication bd) {
if (bd.isProxyed) {
ClassWriter cw = new ClassWriter();
byte[] b = cw.getByteArray();
return defineClass(name, b, 0, b.length);
} else {
bd.getClass();
}
}
}

这个可能是Spring 生成类的方式

2.2.4转换类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class ChangeVersionAdapter extends ClassVisitor {
public ChangeVisionAdapter(ClassVisitor cv) {
super (ASM4, cv);
}

@Override
public void visit(int version, int access, String name,
String signature, String superName, String[] interfaces) {
cv.visit(V1_6, access, name, signature, superName, interfaces);
}
}

try (InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("path")) {
int size = inputStream.available();
byte[] bytes = new byte[size];
inputStream.read(bytes);
ClassReader classReader = new ClassReader(bytes);
ClassWriter classWriter = new ClassWriter(classReader , 0);
ClassVisitor classVisitor = new ChangeVersionAdapter(classWriter);
classReader.accept(classVisitor, 0);
} catch (Exception e) {
e.printStackTrace();
}

2.2.5 移除类成员

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class RemoveMethodAdapter extends ClassVisitor {
private String mName;
private String mDesc;
public RemoveMethodAdapter(ClassVisitor cv, String mName, String mDesc) {
super(ASM4, cv);
this.mName = mName;
this.mDesc = mDesc;
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
if (name.equals(mName) && desc.equals(mDesc)) {
return null;
}
return cv.visitMethod(access, name, desc, signature, exceptions);
}
}

2.2.6 增加类成员

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
public class AddFieldAdapter extends ClassVisitor {
private int fAcc;
private String fName;
private String fDesc;
private boolean isFieldPresent;

public AddFieldAdapter(ClassVisitor cv, int fAcc, String fName, String fDesc) {
super(ASM4, cv);
this.fAcc = fAcc;
this.fName = fName;
this.fDesc = fDesc;
}

public FieldVisitor fieldVisitor(int access, String name, String desc, String signature, Object value) {
if (name.equals(fName)) {
isFieldPresent = true;
}
return cv.visitField(access, name, desc, signature, value);
}

@Override
public void visitEnd() {
if (! isFieldPresent) {
FieldVisitor fv = cv.visitField(fAcc, fName, fDesc, null, null);
if ( fv != null) {
fv.visitEnd();
}
}
cv.visitEnd();
}
}

我们只是检测一下我们我们要添加的字段是不是存在的, 如果不存在的话,我们进行字段的添加

2.2.7 转化链

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class MultiClassAdapter extends ClassVisitor {
protected ClassVisitor[] cvs;

public MultiClassAdapter(ClassVisitor[] cvs) {
super(ASM4);
this.cvs = cvs;
}

@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
for (ClassVisitor cv : cvs) {
cv.visit(version, access, name, signature, superName, interfaces);
}
}
}

2.2.8 TraceClassVisitor & CheckClassAdapter

  • TraceClassVisitor

    以获得关于实际所生成内容的一个可读轨迹

  • CheckClassAdapter

    验证其对方法的调用顺序是否恰当,参数是否有效,然后才会委托给一下个防蚊器。当发生错误时,会抛出IllegaStateException或IllegalArgumentException

1
2
3
ClassWriter cw = new ClassWriter(0);
TraceClassVisitor tcv = new TraceClassVisitor(cw, printWriter);
CheckClassA