一:扫描 classPathBeanDefinitionScanner
扫描了指定路径下面的所有包里面的类,来过滤是否有满足可以加入SpringBean属性 然后初始化BeanDefinition的基本属性 ,最后注册到一个Map里面
registerBeanDefinition 之后就初始完BeanDinition
this.beanDefinitionMap.put(beanName, beanDefinition);
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
//拿到需要扫描的包(会有多个)
for (String basePackage : basePackages) {
//获取符合条件的beanDefinition 也就是候选人的意思
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
//这个是一个元数据 利用了反射框架 仅此
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
//一般是BeanClassname 有些是内部类会做一些其他操作
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
//初始化 beanDefinition 有设置懒加载属性和Autowrite
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
//初始化注解信息
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
//判断当前类是否在Spring容器里面加载过
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
//注册BeanDefinition
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
二:合并父子类
我将关键的代码贴出来,判断这个Bean 是否有父类,有就重复调用合并的方法, 每次调用都是创建一个新的对象出来,存储到mergedBeanDefinitions 这个map里面,并且这个名字对应的对象还可能会被重新合并.
if (!beanName.equals(parentBeanName)) {
//这里是一个递归方法 ~
pbd = getMergedBeanDefinition(parentBeanName);
}
/** Map from bean name to merged RootBeanDefinition. */
private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256);
三:加载Class文件
BeanDefinition 合并之后,就可以创建Bean的对象了,那基本上就是加载Class文件,那接下来的代码其实就是GetBean 里面的代码
(createBean)
//加载类对象
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
四:实例化前操作
实现,InstantiationAwareBeanPostProcessor 是一个扩展点,有实例化前操作,比如你直接返回一个对象,name他就不去new了
@Component
public class DpyuyuBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
System.out.println("实例化前");
}
return null;
}
}
五: 实例化过程
在这个步骤中就会根据BeanDefinition去创建一个对象了。
5.1: 首先判断BeanDefinition中是否设置了Supplier,如果设置了则调用Supplier的get()得到对象。 5.2: 如果没有设置Supplier,则检查BeanDefinition中是否设置了factoryMethod,也就是工厂方法,有两种方式可以设置factoryMethod,比如: 5.3: 在推断构造方法逻辑中除开会去选择构造方法以及查找入参对象意外,会还判断是否在对应的类中是否存在使用 @Lookup注解了方法。如果存在则把该方法封装为LookupOverride对象并添加到BeanDefinition中。
在实例化时,如果判断出来当前BeanDefinition中没有LookupOverride,那就直接用构造方法反射得到一个实例对象。如果存在LookupOverride对象,也就是类中存在@Lookup注解了的方法,那就会生成一个代理对象。
六: BeanDefinition的后置处理 MergedBeanDefinitionPostProcessor
Bean对象实例化出来之后,接下来就应该给对象的属性赋值了。在真正给属性赋值之前,Spring又提供了一个扩展点MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition() ,可以对此时的BeanDefinition进行加工,比如:可以直接将其重新赋值,或者将字段进行重新赋值
@Component
public class DpyuyuMergedBeanDefinitionPostProcessor implements MergedBeanDefinitionPostProcessor {
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
if ("userService".equals(beanName)) {
beanDefinition.getPropertyValues().add("orderService", new OrderService());
}
}
}
七 实例化后 InstantiationAwareBeanPostProcessor
在处理完BeanDefinition后,Spring又设计了一个扩展点:InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() ,比如: 这个扩展点,就是对User对象进行使用,但是Spring用的少
@Component
public class DpyuyuInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
UserService userService = (UserService) bean;
userService.test();
}
return true;
}
}
八:处理属性 InstantiationAwareBeanPostProcessor
处理@Autowired、@Resource、@Value等注解,该功能也是通过 InstantiationAwareBeanPostProcessor 接口来实现的,或者我们也可以自己写一个注解 或者说可以利用他写一个aop后置处理啥的
@Component
public class DpyuyuInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
for (Field field : bean.getClass().getFields()) {
if (field.isAnnotationPresent(DpyuyuInject.class)) {
field.setAccessible(true);
try {
field.set(bean, "123");
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
return pvs;
}
}
九:执行 Aware
完成了属性赋值之后,Spring会执行一些回调,包括:
BeanNameAware:回传beanName给bean对象。 BeanClassLoaderAware:回传classLoader给bean对象。 BeanFactoryAware:回传beanFactory给对象。
十:初始化前 postProcessBeforeInitialization
类似实例化前,都是spring提供的扩展点,该扩展点 postProcessBeforeInitialization ,这里实现的接口其实返回的已经是bean,可以对该Bean 进行数据处理,比如 是否有权限处理等操作,
@Component
public class DpyuyuBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
System.out.println("初始化前");
}
return bean;
}
}
在Spring源码中:
InitDestroyAnnotationBeanPostProcessor会在初始化前这个步骤中执行@PostConstruct的方法,
ApplicationContextAwareProcessor会在初始化前这个步骤中进行其他Aware的回调:
EnvironmentAware:回传环境变量
EmbeddedValueResolverAware:回传占位符解析器
ResourceLoaderAware:回传资源加载器
ApplicationEventPublisherAware:回传事件发布器
MessageSourceAware:回传国际化资源
ApplicationStartupAware:回传应用其他监听对象,可忽略
ApplicationContextAware:回传Spring容器ApplicationContext
十一: 初始化
查看当前Bean对象是否实现了InitializingBean接口,如果实现了就调用其afterPropertiesSet()方法 执行BeanDefinition中指定的初始化方法 ###
十二: 初始化后 BeanPostProcessor
可以在这个步骤中,对Bean最终进行处理,Spring中的AOP就是基于初始化后实现的,初始化后返回的对象才是最终的Bean对象。
@Component
public class DpyuyuBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
System.out.println("初始化后");
}
return bean;
}
}
补充: 实例化后将是自动注入的逻辑-
总结:
1: 扫描类,然后生成BeanDefinition
2: 生成BeanDefinition
3: 加载Class
4: 实例化前-InstantiationAwareBeanPostProcessor class文件和BeanName
5: 实例化 多种
6: 实例化之后修改RootBeanDefinition MergedBeanDefinitionPostProcessor
7: 实例化后 InstantiationAwareBeanPostProcessor 这时就有对象了
8: (这里常规应该自动注入)
9: 处理属性 也是InstantiationAwareBeanPostProcessor 一些注解的功能也是这里实现的
10: 执行Aware 类似回调
11: 初始化前 BeanPostProcessor postProcessBeforeInitialization
12: 初始化 afterPropertiesSet 或者 BeanDefinition
13: 初始化后 BeanPostProcessor postProcessAfterInitialization