补充一句,上一篇bean的创建过程在bean实例化之后为属性赋值是使用BeanUtils这个工具类来完成的,可以学一下BeanUtils的使用。
bean准备阶段
01
编写一个配置类:SpringConfig.java(所在包:wjy.stu.config),使用@Configuration注解。
02
编写bean类:UserBean、ScoreBean(所在包:wjy.stu.bean)使用@Component注解,
UserDao(所在包wjy.stu.dao)使用@Repository注解
03
在配置类SpringConfig.java上添加注解
@ComponentScans(
{
@ComponentScan("wjy.stu.bean"),
@ComponentScan("wjy.stu.dao")
}
)
04
编写一个BeanFactoryPostProcessor:MyBeanFactoryPostProcessor,实现postProcessBeanFactory方法打印bean工厂中所有的bean的名称。
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
String[] names = beanFactory.getBeanDefinitionNames();
// 获取了所有的bean名称列表
for(int i=0; i<names.length; i++){
String name = names[i];
BeanDefinition bd = beanFactory.getBeanDefinition(name);
System.out.println(name + " bean properties: \n" + bd.getPropertyValues().toString());
}
}
05
编写一个BeanPostProcessor:MyBeanPostProcessor,实现接口中的方法。
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessBeforeInitialization==>" + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInitialization==>" + beanName);
return bean;
}
06
在配置类SpringConfig.java上添加
@Import({MyBeanFactoryPostProcessor.class, MyBeanPostProcessor.class})
07
在main方法中使用AnnotationConfigApplicationContext启动spring容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
AnnotationConfigApplicationContext工作流程
分两步分析:
- registerBean方法内部执行流程分析
- refresh方法
本篇先介绍registerBean方法内部执行流程分析
01
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this();
register(annotatedClasses);
refresh();
}
02
实例化AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner。
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
03
父类GenericApplicationContext的构造方法
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
04
AnnotationConfigApplicationContext实现
AnnotationConfigRegistry接口的register方法
public void register(Class<?>... annotatedClasses) {
this.reader.register(annotatedClasses);
}
05
AnnotationConfigApplicationContext的register方法最后调用的是AnnotatedBeanDefinitionReader类的register方法
【AnnotatedBeanDefinitionReader类】
public void register(Class<?>... annotatedClasses) {
for (Class<?> annotatedClass : annotatedClasses) {
registerBean(annotatedClass);
}
}
06
最终调用 AnnotatedBeanDefinitionReader::registerBean(Class<?> annotatedClass, String name, Class<? extends Annotation>… qualifiers)方法完成bean的注册。
registerBean方法内部执行流程分析:
分析AnnotatedBeanDefinitionReader类的registerBean方法。
01
根据annotatedClass构造一个BeanDefinition
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
AnnotatedGenericBeanDefinition的构造方法
public AnnotatedGenericBeanDefinition(Class<?> beanClass) {
setBeanClass(beanClass);
this.metadata = new StandardAnnotationMetadata(beanClass, true);
}
StandardAnnotationMetadata类:
在StandardAnnotationMetadata构造方法中获取了这个bean的Class对象上的所有注解
public StandardAnnotationMetadata(Class<?> introspectedClass, boolean nestedAnnotationsAsMap) {
super(introspectedClass);
this.annotations = introspectedClass.getAnnotations();
this.nestedAnnotationsAsMap = nestedAnnotationsAsMap;
}
02
获取scope元数据,即描述scope的数据,scope信息
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
先来了解一个接口:ScopeMetadataResolver,用于解析bean定义范围的策略接口。
public interface ScopeMetadataResolver {
//解析bean定义范围,返回一个描述bean定义范围的对象ScopeMetadata
ScopeMetadata resolveScopeMetadata(BeanDefinition definition);
}
AnnotatedBeanDefinitionReader的scopeMetadataResolver是ScopeMetadataResolver的实现类AnnotationScopeMetadataResolver。
@Override
public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
ScopeMetadata metadata = new ScopeMetadata();
if (definition instanceof AnnotatedBeanDefinition) {
AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
//获取注解类型是this.scopeAnnotationType类型的属性,
//protected Class<? extends Annotation> scopeAnnotationType = Scope.class;
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(
annDef.getMetadata(), this.scopeAnnotationType);
if (attributes != null) {
//获取scope的value值
metadata.setScopeName(attributes.getString("value"));
......
}
}
return metadata;
}
03
给AnnotatedGenericBeanDefinition设置scope
abd.setScope(scopeMetadata.getScopeName());
04
获取beanName,如果registerBean没有指定name则根据bean名称产生器产生一个beanName
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
bean名称产生器接口:BeanNameGenerator
public interface BeanNameGenerator {
/**
* 为给定的bean定义生成bean名称。
* 参数1:BeanDefinition
* 参数2:BeanDefinition注册器
*/
String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry);
}
这里使用的是它的实现类AnnotationBeanNameGenerator
@Override
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
if (definition instanceof AnnotatedBeanDefinition) {
//调用determineBeanNameFromAnnotation方法获取
String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition);
if (StringUtils.hasText(beanName)) {
return beanName;
}
}
return buildDefaultBeanName(definition, registry);
}
protected String determineBeanNameFromAnnotation(AnnotatedBeanDefinition annotatedDef) {
//获取注解元数据,描述该bean的注解信息
AnnotationMetadata amd = annotatedDef.getMetadata();
//获取该bean的所有注解的类型
Set<String> types = amd.getAnnotationTypes();
String beanName = null;
for (String type : types) {
//获取注解类型上的属性
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(amd, type);
//调用isStereotypeWithNameValue方法判断当前注解类型是否是@Component类型
//或者被@Component注释的类:如@Service (org.springframework.stereotype包下的注解都是)
//并且当前注解的属性中是否有名为“value”的属性。
if (isStereotypeWithNameValue(type, amd.getMetaAnnotationTypes(type), attributes)) {
//获取注解的value属性的值,如果存储value属性的话
Object value = attributes.get("value");
if (value instanceof String) {
String strVal = (String) value;
if (StringUtils.hasLength(strVal)) {
if (beanName != null && !strVal.equals(beanName)) {
如果value的值与上一次循环获取的beanName不同抛出异常。
这是防止被@Service注解之后又使用@Component注解的情况
}
beanName = strVal;
}
}
}
}
return beanName;
}
protected boolean isStereotypeWithNameValue(String annotationType,
Set<String> metaAnnotationTypes, Map<String, Object> attributes) {
//如果注解类型annotationType是org.springframework.stereotype.Component
//或者annotationType上有org.springframework.stereotype.Component注解,
//比如:
//@Component
//public @interface Repository
//即@Repository上被@Component注释
boolean isStereotype = annotationType.equals(COMPONENT_ANNOTATION_CLASSNAME) ||
(metaAnnotationTypes != null && metaAnnotationTypes.contains(COMPONENT_ANNOTATION_CLASSNAME)));
//如果isStereotype条件成立且attributes不为空,且attributes中含有value属性,那么返回true。
//attributes是annotationType注解的所有属性
return (isStereotype && attributes != null && attributes.containsKey("value"));
}
如果前面注解都没有指定value,则调用buildDefaultBeanName方法把bean的类名作为bean的名称,首字母小写。
protected String buildDefaultBeanName(BeanDefinition definition) {
String shortClassName = ClassUtils.getShortName(definition.getBeanClassName());
return Introspector.decapitalize(shortClassName);
}
05
beanName获取到之后就是处理常用的定义注解
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
AnnotationConfigUtils注解配置工具类的processCommonDefinitionAnnotations方法,
参数1是AnnotatedBeanDefinition,参数2是AnnotatedBeanDefinition的getMetadata()方法获取到的注解类型描述信息
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
//@Lazy注解
if (metadata.isAnnotated(Lazy.class.getName())) {
abd.setLazyInit(attributesFor(metadata, Lazy.class).getBoolean("value"));
}
else if (abd.getMetadata() != metadata && abd.getMetadata().isAnnotated(Lazy.class.getName())) {
abd.setLazyInit(attributesFor(abd.getMetadata(), Lazy.class).getBoolean("value"));
}
//@Primary注解
if (metadata.isAnnotated(Primary.class.getName())) {
abd.setPrimary(true);
}
//@DependsOn注解
if (metadata.isAnnotated(DependsOn.class.getName())) {
abd.setDependsOn(attributesFor(metadata, DependsOn.class).getStringArray("value"));
}
if (abd instanceof AbstractBeanDefinition) {
AbstractBeanDefinition absBd = (AbstractBeanDefinition) abd;
//@Role注解
if (metadata.isAnnotated(Role.class.getName())) {
absBd.setRole(attributesFor(metadata, Role.class).getNumber("value").intValue());
}
//@Description注解
if (metadata.isAnnotated(Description.class.getName())) {
absBd.setDescription(attributesFor(metadata, Description.class).getString("value"));
}
}
}
就只是将bean含有以上这些注解的信息读取到AnnotatedBeanDefinition中。
06
new一个BeanDefinition的持有者
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
注册BeanDefinition到bean工厂,createBean的时候才能获取到这个bean的BeanDefinition
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// 在主beanName下注册bean定义。
String beanName = definitionHolder.getBeanName();
//调用的是DefaultListableBeanFactory的registerBeanDefinition方法
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// 注册bean名称的别名(如果有的话)。
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
07
DefaultListableBeanFactory实现了BeanDefinitionRegistry接口。
//---------------------------------------------------------------------
// Implementation of BeanDefinitionRegistry interface
//---------------------------------------------------------------------
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
BeanDefinition oldBeanDefinition;
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
......
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
//hasBeanCreationStarted检查该工厂的bean创建阶段是否已经启动,即是否有任何bean已经标记为在此期间创建。
if (hasBeanCreationStarted()) {
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
//beanDefinitionMap保存的是所有bean的BeanDefinition
this.beanDefinitionMap.put(beanName, beanDefinition);
//beanDefinitionNames保存的是所有bean的名称,
this.beanDefinitionNames.add(beanName);
//单例bean的名称
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
//如果旧的BeanDefinition不为空,且是单例的
if (oldBeanDefinition != null || containsSingleton(beanName)) {
//重置BeanDefinition,同时移除单例的bean
resetBeanDefinition(beanName);
}
}
DefaultListableBeanFactory的resetBeanDefinition方法
protected void resetBeanDefinition(String beanName) {
// 如果已经创建,则删除给定bean的合并bean定义。
clearMergedBeanDefinition(beanName);
// 销毁单例,让gc回收,具体过程就不深入了。
destroySingleton(beanName);
// 重置所有以给定bean为父bean的bean定义。
for (String bdName : this.beanDefinitionNames) {
if (!beanName.equals(bdName)) {
BeanDefinition bd = this.beanDefinitionMap.get(bdName);
if (beanName.equals(bd.getParentName())) {
resetBeanDefinition(bdName);
}
}
}
}
scan包扫描
这里还要补充一个bean的注册流程,就是从包扫描出发的。
01
AnnotationConfigApplicationContext类的另一个构造方法
public AnnotationConfigApplicationContext(String... basePackages) {
this();
scan(basePackages);
refresh();
}
scan方法
public void scan(String... basePackages) {
this.scanner.scan(basePackages);
}
ClassPathBeanDefinitionScanner的scan方法
public int scan(String... basePackages) {
int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
doScan(basePackages);
if (this.includeAnnotationConfig) {
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
}
最后调用doScan方法完成扫描并注册bean。这个方法在第一篇介绍ClassPathBeanDefinitionScanner的时候提到过。
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
for (String basePackage : basePackages) {
//扫描每个basePackages下的bean,findCandidateComponents方法是具体的实现。
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
// 遍历每个BeanDefinition,处理其scope和常用注解
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
// 处理常用定义注解,前面介绍过了
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
if (checkCandidate(beanName, candidate)) {
//registerBeanDefinition 注册BeanDefinition,(注册bean)
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}