《圣经》旧约.创世纪:起初,神创造天地。地是空虚混沌,渊面黑暗; 神的灵运行在水面上。神说:“要有光。”就有了光。 神看光是好的,就把光暗分开了。 神称光为昼,称暗为夜。有晚上,有早晨,这是头一日。
《圣经》旧约.创世纪
目录
2.Spring是如何使用BeanDefinition的呢?
3.1.1 创建AnnotatedBeanDefinitionReader
3.1.2 创建ClassPathBeanDefinitionScanner
1.什么是BeanDefinition?
Spring的Bean具有自己的属性、构造函数参数和很多具体的相关信息。BeanDefinition是用来描述Bean的这些信息的。类似与Java世界中,class Class这个类用来描述各种对象一样。
在java项目中,用户定义的各种xx.java文件要让JVM认识,需要事先通过编译器将其编译成xx.class文件。然后再通过ClassLoader读取xx.class文件将其加载到JMM的方法区Method Area。
在Spring项目中,用户定义了可以让Spring管理的注解类(@Component, @Service, @Repository)。Spring容器初始时,Spring就通过AnnotatedBeanDefinitionReader去获取这些类的注解信息,并将其翻译整合到beanDefinitionMap、beanDefinitionNames两个数据结构的实体中,等待后续的bean实例化过程使用。
BeanDefinition是什么模样呢?
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
int ROLE_APPLICATION = 0;
int ROLE_SUPPORT = 1;
int ROLE_INFRASTRUCTURE = 2;
void setParentName(@Nullable String parentName);
String getParentName();
void setBeanClassName(@Nullable String beanClassName);
String getBeanClassName();
void setScope(@Nullable String scope);
String getScope();
void setLazyInit(boolean lazyInit);
boolean isLazyInit();
void setDependsOn(@Nullable String... dependsOn);
String[] getDependsOn();
void setAutowireCandidate(boolean autowireCandidate);
boolean isAutowireCandidate();
void setPrimary(boolean primary);
boolean isPrimary();
void setFactoryBeanName(@Nullable String factoryBeanName);
String getFactoryBeanName();
void setFactoryMethodName(@Nullable String factoryMethodName);
String getFactoryMethodName();
ConstructorArgumentValues getConstructorArgumentValues();
default boolean hasConstructorArgumentValues() {
return !getConstructorArgumentValues().isEmpty();
}
MutablePropertyValues getPropertyValues();
default boolean hasPropertyValues() {
return !getPropertyValues().isEmpty();
}
void setInitMethodName(@Nullable String initMethodName);
String getInitMethodName();
void setDestroyMethodName(@Nullable String destroyMethodName);
String getDestroyMethodName();
void setRole(int role);
int getRole();
void setDescription(@Nullable String description);
String getDescription();
boolean isSingleton();
boolean isPrototype();
boolean isAbstract();
String getResourceDescription();
BeanDefinition getOriginatingBeanDefinition();
}
从定义中可以看出,BeanDefinition (bd)可以记录bean的相关定义,比如bean父类关系,作用域scope,是否懒加载islazy,依赖对象,是否可以被自动注入isAutowireCandidate,是否是FactoryBean等等常见属性。
2.Spring是如何使用BeanDefinition的呢?
我们以注解方式编写的项目举例来说,首先还是定义几个类:
package com.Hodey.learn.bean;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component("yadang")
public class Adam {
private String name;
@PostConstruct
private void init(){
name = "Adam";
}
public void sayHello(){
System.out.println("你好,我是" + name + ".");
}
}
package com.Hodey.learn.bean;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component("xiawa")
public class Eve {
private String name;
@PostConstruct
private void init(){
name = "Eve";
}
public void sayHello(){
System.out.println("你好,我是" + name + ".");
}
}
package com.Hodey.learn.bean;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;
@Component
@DependsOn("xiawa")
public class Human {
public void sayHello(){
System.out.println("大家好,欢迎来到伊甸园!");
}
}
package com.Hodey.learn.service;
import com.Hodey.learn.bean.Adam;
import com.Hodey.learn.bean.Eve;
import com.Hodey.learn.bean.Human;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class GardenofEden {
@Autowired
private Adam adam;
@Resource(name = "xiawa")
private Eve eve;
@Autowired
private Human human;
public void sayHello(){
adam.sayHello();
eve.sayHello();
human.sayHello();
}
}
package com.Hodey.learn;
import com.Hodey.learn.service.GardenofEden;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
@EnableAutoConfiguration
@ComponentScan("com.Hodey")
public class CaseApplication {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx =
new AnnotationConfigApplicationContext(CaseApplication.class);
GardenofEden garden = ctx.getBean(GardenofEden.class);
garden.sayHello();
}
}
工程结构目录如下:
要知道bd的来龙去脉,还得从Spring容器创建过程说起。
3. Spring容器的初始化过程
创建AnnotationConfigApplicationContext(CaseApplication.class),按照java的语法规则会先行调用其父类的构造方法,然后才调用自身的构造函数进行对象的创建。在DefaultResourceLoader中会初始化以下三个属性:
//类加载器Launcher$AppClassLoader
private ClassLoader classLoader;
//协议解析器容器
private final Set<ProtocolResolver> protocolResolvers = new LinkedHashSet<>(4);
//配置文件缓存器
private final Map<Class<?>, Map<Resource, ?>> resourceCaches = new ConcurrentHashMap<>(4);
在AbstractApplicationContext类中主要初始化:
//确定日志类型,比如log4j,logback
protected final Log logger = LogFactory.getLog(getClass());
//创建beanFactory后置处理器
private final List<BeanFactoryPostProcessor> beanFactoryPostProcessors = new ArrayList<>();
//创建事件监听器容器
private final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();
/*resourceLoader:AnnotationConfigApplicationContext
* pathMatcher: AntPathMatcher ant风格的解析器 */
private ResourcePatternResolver resourcePatternResolver;
在GenericApplicationContext中创建Spring IoC最重要的对象beanFactory。
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
最后才会调用AnnotationConfigApplicationContext(CaseApplication.class)的构造函数完成Spring容器的创建和初始化工作。
/* 输入若干个注解类,推导出其beanDefinition,之后自动刷新容器 */
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this();//1.调用无参构造函数
register(annotatedClasses);//2.将若干个配置类进行注册
refresh();//3.refresh容器
}
3.1.无参构造函数
进入其无参构造函数会发现容器的reader和scanner成员属性被创建出来。下面来看reader的创建过程。
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
3.1.1 创建AnnotatedBeanDefinitionReader
this.reader = new AnnotatedBeanDefinitionReader(this); this代表的是AnnotationConfigApplicationContext对象本身。回头再看看上面的类关系图谱,会发现AnnotationConfigApplicationContext对象本身就可以看作是BeanDefinitionRegistry,ResourceLoader和BeanFactory。依次进入其构造方法,最关键的一步是AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)。
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
//创建一个标准的环境对象StandardEnvironment
//如果是web应用,这个环境对象将是StandardServletEnvironment
//在SpringBoot项目中,该对象会被SpringBoot内核自动推断出来
this(registry, getOrCreateEnvironment(registry));
}
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
this.registry = registry;
//用于对含有@Condition注解的类进行特殊解析
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
//关键步骤
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
进入到该步骤的干货处:
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
//从registry也就是AnnotationConfigApplicationContext中获取之前注册到它身上的bean工厂。
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
/**
* 向Spring的beanFactory身上添加两个处理注解能力
* 1. AnnotationAwareOrderComparator是处理@oder和@Priority
* 2. ContextAnnotationAutowireCandidateResolver是处理@Lazy
*/
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
/**
* 以下是向bean工厂添加若干个Spring内部的配置类,这些配置类定义在org.springframework.context.annotation.AnnotationConfigUtils中
* 1.defaultListableBeanFactory.beanDefinitionMap中添加配置类的<name ,bd>
* 2.defaultListableBeanFactory.beanDefinitionNames中添加bd的name
*/
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
//将返回的holder放入beanDefs这个Set中,其实并没有返回给外层
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition();
try {
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}
return beanDefs;
}
最终添加的bd是以下5个。
//配置类处理器
1.org.springframework.context.annotation.internalConfigurationAnnotationProcessor
//自动注入类处理器
2.org.springframework.context.annotation.internalAutowiredAnnotationProcessor
//通用注解类处理器
3.org.springframework.context.annotation.internalCommonAnnotationProcessor
4.org.springframework.context.event.internalEventListenerProcessor
5.org.springframework.context.event.internalEventListenerFactory
注册PostProcessor的代码是registerPostProcessor(registry, def, XXX)。
private static BeanDefinitionHolder registerPostProcessor(
BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
//role有三个取值:ROLE_APPLICATION=0 代表是应用创建的bean
// ROLE_SUPPORT=1 代表某些起支持类作用的bean,比如在一些大型的configuration类中
// ROLE_INFRASTRUCTURE=2 Spring内部自己使用的bean,不对用户开放
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
//向defaultListableBeanFactory.beanDefinitionMap中添加配置类的<name ,bd>
//向defaultListableBeanFactory.beanDefinitionNames中添加bd的name
registry.registerBeanDefinition(beanName, definition);
//返回一个holder,其实并没什么卵用
return new BeanDefinitionHolder(definition, beanName);
}
当上述5个bd都完成注册后,reader 的创建和初始化过程就结束了。
3.1.2 创建ClassPathBeanDefinitionScanner
还是老规矩,先构造父类,再调用子类构造方法完成创建和初始化工作。父类的工作很简单,
ClassPathScanningCandidateComponentProvider
//定义了扫描resource文件的路径
private String resourcePattern = "**/*.class"
private final List<TypeFilter> includeFilters = new LinkedList<>();
private final List<TypeFilter> excludeFilters = new LinkedList<>();
子类ClassPathBeanDefinitionScanner的主要构建过程如下
public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {
//dependencyCheck= DEPENDENCY_CHECK_NONE 默认不会进行依赖检查
//autowireMode=AUTOWIRE_NO 默认的自动装配模式是NO,可以参考官网或者我的上一篇文章《关于Spring自动装配几个你所不知道的事》
private BeanDefinitionDefaults beanDefinitionDefaults = new BeanDefinitionDefaults();
//创建一个AnnotationBeanNameGenerator 可以参考官网或者我的上一篇文章《关于Spring自动装配几个你所不知道的事》
private BeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();
//创建 @Scope注解类的解析器,并且默认不使用代理模式
private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();
private boolean includeAnnotationConfig = true;
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
this(registry, true);
}
}
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
Environment environment, @Nullable ResourceLoader resourceLoader) {
this.registry = registry;
if (useDefaultFilters) {
//在scaner.includeFilters中添加javax.annotation.ManagedBean和javax.inject.Named两种注解类型filter
//@javax.annotation.ManagedBean是JAVA EE6自身提供的注解类
//@Inject、@Named、@Qualifier和@Provider是属于javax.inject.Named
registerDefaultFilters();
}
setEnvironment(environment);
setResourceLoader(resourceLoader);
}
至此,AnnotationConfigApplicationContext.scaner就创建和初始化完毕了。随着scaner的初始化完毕,Spring容器的创建阶段就基本告一段落了。
如果将00:00-7:00的时刻表映射到Sping的启动流程的话,目前的时间大致应该是在00:30左右。夜生活才刚刚开始,后续文章敬请期待!