spring生命周期上:
要注意的是spring启动的时候已经经过了spring的生命周期了
transformBeanName(name)
getSingleton(beanName)是可以拿到
getObjectForBeanInstance 是不是factoryBean
name 程序员传入、beanName 真名
双重机制校验
普通bean直接返回
是factoryBean执行下面的逻辑
从缓存中调用
factoryObejctCanche
当前缓存没有 强制转换成factoryBean ,因为他要调用getObject方法
doGetObjectFromFactoryBean
// 调用BeanPostProcessor执行初始化后的逻辑,主要就是进行AOP
调用初始化之后的方法 因为他可能要进行aop做动态代理
得到的对象要看他是不是实现了factoryBean
所以FactoryBean相当于是懒加载 。只有在调用getBean(factoryBeanName)的时候才会调用getObject方法去获取User 对象
getObject的user对象会放到容器中:
就是factoryBeanObjectCache 容器中 而LubanFactoryBean就会放到singletonObjects 0:41:00
beanFactroy是大工厂 ,spring中所有的Bean 都是由BeanFactory创建出来的 。它可以创建普通bean 和特殊bean 、单例bean原型bean
FactoryBean是通过beanFactory 创建出来的
FactoryBean是一个小的工厂 ,只能产生一个对象。 或者scope是 原型的 ,可以产生同一个类型的多个对象
factoryBean的作用 有的时候我们希望自己构造一个对象,把他放到Ioc容器中
这边getBean("user") 拿不到User这个对象 ,因为这个User对象不是一个配置类, 不能够生成Bean定义
@component
public class UserService{
@Autowired
private UserMapper userMapper;
}
UserMapper接口 ,需要把UserMapper接口的代理对象注册到Ioc容器中。。 既可以有代理对象 又需要注册到容器中
在我们的容器中我们需要一个UserMapper的代理对象
还有啥方式: 如何把我们自己new 出来的对象 放到容器中呢??
1、@Bean 功能比较单一 ,只能写在方法上 , 这个方法内部也能够 弄一个代理对象出来
2、class 实现 FactoryBean 接口之外,还能够 实现其他接口 BeanClassLoaderAware
回调函数可以 拿到这个类是哪个 类加载器加载
00:00 - 00:58:543 都在讲一个东西就是FactoryBean
bean的生命周期
进行扫描,扫描类
生成Bean
推断构造方法 , 加载类之后要实例化对象的话,多 个构造方法要选哪一个呢 所以会去推断构造方法
属性赋值就是依赖注入
有一个问题,当我们在扫描的时候,扫描到userService这个类的时候,我们没有去加载这个类,我们说的加载这个类指的是生成这个类的class
对象放到jvm中去,我们在扫描的时候没有做到这一步。。。 那我们如何发现UserService这个类上面是否有component这个注解呢 ,第一步进行扫描,然后我们用的asm技术
解析字节码文件 识别这个类的信息 生成一个beanDefintion
入口 :
怎样实例化非懒加载的单例ban
合并之后的bd 叫做rootBd
合并之前的叫做 genericBd
bd常用的类型
bd是接口 有实现类
genericbd 是支持拥有父
rootbd 不支持parent
创建bean 一定是拿合并之后的bd 就是拿rootbd,
不会去改扫描出来的bd 就是genricBd
就只是会生成mergedBd
beanName --》mergedMap ==》genercicBeanDefintion -parent -》rootBeanDefintion
合并bean定义
@dependSon 注解
程序员自定义的
a depends on b
b depends on a
无法创建
@component
@dependson("orderService")
public class UserService(){
}
@component
@dependson("userService)
public class OrderService(){
}
RequestScope AbstractRequestAttributesScope
SessionScope AbstractRequestAttributesScope
"RequestScope":RequestScope
"session":SessionScope
get方法
结论:
"request" ,UserService -->>Bean对象 request.getAttribute().get("beanName")
"session" ,UserService -->>Bean对象 session.getAttribute().get("beanName")
doCreateBean spring自带的创建方法
resolveBeforeInstantiation(beanName, mbdToUse); 让程序员自己返回一个bean 实现方法用bean的后置处理器
bean的后置处理器 ,spring在创建bean的过程中,我们可以设置一些bean的后置处理器去干涉soring创建bean的过程
实例化之前的bean后置处理器 得到bean 则再执行初始化后的bean后置处理器 因为它跟aop 有关系 不能够拒绝aop
填充属性 @Autowired
populateBean(beanName, mbd, instanceWrapper); //
初始化 和 BeanPostProcessor 正常AOP BeanPostProcessor
exposedObject = initializeBean(beanName, exposedObject, mbd);
initializeBean 中 1、 执行aware
2、 初始化之前 @pointConstruct
3、初始化 调用 实现了InitializingBean 接口的
4、 初始化后
对于任何一个bean 他都有一个beanName
还要判断从单例池拿到的bean是不是一个factoryBean
如果是原型的就直接去创建bean 不去单例池拿了
createBean 是如何创建Bean
第一步:
加载类
beanName mbd
如何返回class对象
AbstractBeanDefinition 的
@Nullable
private volatile Object beanClass; // String Class
获取BeanDefinition中所指定的beanClass属性的值,beanClass属性的类型为Object,可以指定为某个类名
// className可以有SpEL,所以需要解析
@Component
public class UserService(){
@value("#{orderService}") // 可以注入成功
private OrderService orderService;
public void test (){
sout(orderService;)}
}
@value("#{orderService1}") 报错
表示是表达式
@value("${orderService1}") 报错
$表示是占位符 需要填充 用什么填充呢 ,用的是spring的Enviroment
1、定义properties
2、vm options 的时候指定 -D LunbanXX=123
@Autowired 是先byType 再byName
rootbeandefintion 中 beanclass = "com.lunban.UserService"
beanClass 是一个全限定名去加载类,然后重新设置回bean的class属性
asm技术
spring用什么类加载器 去加载类呢 ?
AbstractBeanFactory
@Nullable
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
Thread.CurrentThread().setContextClassLoader(XXX);
applicationContext.getBeanFactroy().setBeanClassLoder(xxx) 程序员自己指定的类加载器
会利用BeanFactory所设置的类加载器来加载类,。
AbstractBeanFactory 类
@Nullable
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
如果没有上面的BeanFactory没有设置,则默认使用ClassUtils.getDefaultClassLoader()所返回的类加载器来加载
ClassUtils.getDefaultClassLoader()
- 优先获取当前线程中的ClassLoader(正常情况下,就是AppClassLoader)
- 如果为空,则获取加载ClassUtils类的类加载器(正常情况下,就是AppClassLoader,但是如果是在Tomcat中运行,那么则会是Tomcat中为每个应用所创建的WebappClassLoader,tomcat会在前面设置)
- 如果为空,那么则是bootstrap类加载器加载的ClassUtils类,那则获取系统类加载器进行加载 系统类加载器默认返回的是appClassLoader
luban 第三期spring生命周期下 00:53:19
什么叫做bootstrap加载 ,spring项目的jar包放到 jre/lib下 放到这个目录下面的类 都会用bootstrap 加载
类加载器的 看jvm 里面有讲。。。。。。。。。
// 如果没有设置,则默认使用ClassUtils.getDefaultClassLoader()所返回的类加载器来加载
如果BeanFactory所设置的类加载器来加载类为空,则获取加载ClassUtils类的类加载器(正常情况下,就是AppClassLoader,但是如果是在Tomcat中运行,那么则会是Tomcat中为每个应用所创建的WebappClassLoader)
asm技术解析字节码生成bd文件
Object bean = resolveBeforeInstantiation(beanName, mbdToUse); // 对象 在doCreateBean之前
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
// 4.1、执行Aware
invokeAwareMethods(beanName, bean); BeanNameAware BeanClassLoaderAware BeanFactoryAware
UserService 实现了InitializingBean,ApplicatioContextAware(对ApplicationContextAwareProcessor)
// 4.2、初始化前
ApplicatioContextAware 在 初始化前执行 对ApplicationContextAwareProcessor ---》applyBeanPostProcessorsBeforeInitialization
// 4.2、初始化前
@pointConstruct注解 ---》applyBeanPostProcessorsBeforeInitialization InitDestroyAnnotationBeanPostProcess --》 找注解 pointConstruct注解 preDestroy 注解
InitDestroyAnnotationBeanPostProcess -》CommonAnnotationBeanPostProcess 的父类
// 4.3、初始化
afterPropertiesSet 在初始化时候执行 ---》invokeInitMethods(beanName, wrappedBean, mbd);
有一个判断逻辑 为什么 不行 ,因为luBanBeanPostProcess 的postProcessBeforeInitialization 方法返回空了,而且因为luBanBeanPostProcess 优于InitDestroyAnnotationBeanPostProcess 执行,只要保证
luBanBeanPostProcess 的postProcessBeforeInitialization 方法执行不为空 就能让 CommonAnnotationBeanPostProcess(InitDestroyAnnotationBeanPostProcess) 执行 的postProcessBeforeInitialization (调用@pointConStruct方法)
@Override
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;
}
上一个beanPostProcess 执行完之后没有返回 下一个bpp 就不会执行
加载类
实例化前 --》 bpp InstantiationAwareBeanPostProcessor 只有他有 postProcessBeforeInstantiation
实例化
BeanDefinition的后置处理 --》 对bd进行操作 BeanDefinition的后置处理 MergedBeanDefinitionPostProcessor --》 postProcessMergedBeanDefinition
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
// 运行修改合并好了的BeanDefinition
// 这里会查找@Autowired的注入点(InjectedElement),并把这些注入点添加到mbd的属性externallyManagedConfigMembers中
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
实例化后 --》 bpp InstantiationAwareBeanPostProcessor 只有他有 postProcessAfterInstantiation
填充属性
填充属性后 --》 InstantiationAwareBeanPostProcessors 中的 postProcessPropertyValues 、postProcessProperties 进行依赖注入
aware
初始化前 --》 bpp postProcessBeforeInitialization
初始化
初始化后 --》 bpp postProcessAfterInitialization
实例化前 --》 bpp InstantiationAwareBeanPostProcessor 只有他有 postProcessBeforeInstantiation 这边返回bean了就直接执行初始化后的方法
初始化后 --》 bpp postProcessAfterInitialization
// 实例化前
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
// beforeInstantiationResolved为null或true
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;
}
// 2、实例化
if (instanceWrapper == null) {
// 创建bean实例 new USerSerive()
instanceWrapper = createBeanInstance(beanName, mbd, args); 这里回进行推造构造方法 , 我们要选哪一个构造方法呢 后面会将
}
实例化前返回对象就不会填充属性
实例化后返回false 就不会填充属性
@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.setInitMethodName("initLuBan");
beanDefinition.getPropertyValues().add("name","xxx");
}
}
}
@component
public class UserService{
public void initLuBan(){
sout("initLuBan");
}
}
在初始化的方法中
invokeInitMethods(beanName, wrappedBean, mbd);
西面这段代码在初始化的最后
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd); // init-method=""
}
}
就会执行这段代码 很六六六 。。
初始化的过程可以做验证 。。。。。 spring提供了各种钩子函数 。。。。