Springboot核心概念
BeanDefinition
在springboot中定义Bean的几种方式
首先是声明式的:
- bean标签xml
- @Bean注解
- @Compent(@Service,@Controller等)
编程式,创建BD然后注册Bean
//new 一个BD
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
// 当前Bean对象的类型
beanDefinition.setBeanClass(User.class);
// 将BeanDefinition注册到BeanFactory中
DefaultListableBeanFactory beanFac tory = new DefaultListableBeanFactory();
beanFactory.registerBeanDefinition("user", beanDefinition);
// 获取Bean
System.out.println(beanFactory.getBean("user"));
BeanDefinition可以理解为底层源码级别的一个概念,也可以理解为Spring提供的一种API使用的方式。
Bean生命周期
FactroyBean与别名问题
FactoryBean基本使用
FactroyBean是懒加载
在spring整合Mybatis中,注入的UserMapper就是Beanfactory实现的,继承FactroyBean之后,在getObjects方法中进行动态代理。
是BeanFactory容器的一个Bean,实现了FactoryBean接口就有三个方法
@Override
public Object getObject() throws Exception {
return new User();
}
@Override//Bean类型
public Class<?> getObjectType() {
return User.class;
}
@Override//对象是不是单例的
public boolean isSingleton() {
return false;
}
}
再从容器中getBean(“lubanFactoryBean”)得到的是User对象,如果想要得到lubanFactoryBean,就要getBean("&lubanFactoryBean").
FactoryBean对应两个对象:
FactoryBean —>&lubanFactoryBean
User---->lubanFactoryBean.
当我们从单例池中拿到Bean之后,判断Bean是否是factroryBean
如果是name是&开头,直接调用factoryBean方法生成对象,放入到factoryBeanObjectCache中去(单例)。
懒加载
SmartFactroy
多了一个isEagerInit,默认返回false懒加载
返回true就是在容器初始化的时候加载
BeanName
Bean的名字有三种情况
beanname:标准名
alias:别名
&beanname:与FactoryBean有关
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// 对beanName进行转换 name如果是"&lubanFactoryBean",那么beanName就是"lubanFactoryBean"
final String beanName = transformedBeanName(name);
先看是不是&开头的名字,是的话直接截掉&符号,
Assert.notNull(name, "'name' must not be null");
// 如果beanName没有以&开头,则直接返回
if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) { // lubanFactoryBean
return name;
}
// 如果beanName以&开头,截取&后的beanName,并且把截取前后的name存在transformedBeanNameCache中
return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
do {
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
return beanName;
});
然后在从别名Map中找
aliasMap中key:alias,values:beanName。
public String canonicalName(String name) {
String canonicalName = name;
// Handle aliasing...
String resolvedName;
do {
resolvedName = this.aliasMap.get(canonicalName); // 别名:beanName
if (resolvedName != null) {
canonicalName = resolvedName;
}
}
while (resolvedName != null);
return canonicalName;
}
之后再从单例池中拿到对象,再判断是不是beanInstance instanceof FactoryBean,是的话调用getObject方法,不是的话直接返回
容器初始化单例Bean
AnnotationConfigApplicationContext中的一个属性DefaultListableBeanFactory,来实现继承自BeanFactroy的方法
preInstantiateSingletons() 方法初始化单例Bean
1.合并BD
BD有两个重要实现类
RootBD,GBD
GBD是合并之前,RBD是合并之后的
扫描解析生成的BDM---->存放GBD,mergentMap—>RBD
如果某个BeanDefinition存在父BeanDefinition,那么则要进行合并
合并成RootBeanDenfintion—>MergentMap
2.doGetBean()
3.CreanBean()
加载类
这里要注意的是,Spring扫描完之后生成BD,并不是把class加载进jvm反射获取类的元信息,而是通过ASM技术解析class文件获得的,BD的一个属性BeanClass是Object类型的,扫描完成后是String类型,表示类的全限定类名,在这里又会把 BeanClass改为Class类型,也就是该Bean 的Class对象
实例化前
允许第三方可以不按照Spring的正常流程来创建一个Bean,可以利用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法来提前返回一个Bean对象,直接结束Bean的生命周期
如果实例化前返回了一个对象,会直接执行postProcessAfterInitialization初始化后的方法。----初始化后的AOP
推断构造方法
实例化 Instantiation
BeanDefinition的后置处理
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
这里可以处理BeanDefinition,但是此时实例对象已经生成好了,所以修改beanClass已经没用了,但是可以修改PropertyValues,比如:
也可以setInitMethodName(),在初始化的时候会执行。参数是Bean中方法的名字
@Component
public class LubanMergedBeanDefinitionPostProcessor implements MergedBeanDefinitionPostProcessor {
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
if (beanName.equals("userService")) {
beanDefinition.setBeanClass(User.class); // 没用
beanDefinition.getPropertyValues().add("name","xxx");
}
}
}
填充属性
执行Aware
- ((BeanNameAware) bean).setBeanName(beanName);
- ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
- ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
初始化前
Spring中的InitDestroyAnnotationBeanPostProcessor会找到Bean中实现这两个注解的方法,然后把这两个方法放到对应的List集合中去,再调用PostConstrust
@PostConstruct
@PreDestroy
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
@PostConstruct与@PreDestroy
在扫描时会看Bean方法上是否有这两个注解
在4.2时会调用
InitDestroyAnnotationBeanPostProcessor后置处理器处理
构造方法反射得到一个实例,实例化分为四步
// 4.1、执行Aware
invokeAwareMethods(beanName, bean);
// 4.2、初始化前
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
// 4.3、初始化
invokeInitMethods(beanName, wrappedBean, mbd);
// 4.4、初始化后 AOP ()
applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
如果有一个BeanPostProcess调用方法返回空,剩下的就不会执行了,它有一个
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
// BPP1--》BPP2-->BPP3
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
执行完之后没有返回一个对象就不会传入下一个。
初始化 Initialization
- ((InitializingBean) bean).afterPropertiesSet();
- 执行BeanDefinition中指定的初始化方法invokeInitMethods
初始化后
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}