马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
前言
在之前的文章中,我们介绍了 Bean 的核心概念、Bean 定义的解析过程以及 Bean 创建的准备工作。在今天的文章中,我们将深入探讨 Bean 的创建过程,并主要讲解 createBean 方法的实现。在这个过程中,我们将了解 Bean 的实例化、属性注入、初始化和销毁等步骤,以及各个步骤的具体实现细节。通过本文的学习,读者将能够更深入地理解 Spring 框架中 Bean 的创建过程,从而为后续的学习和实践打下坚实的基础。好了,我们开始!
createBean
前面我们说过,最开始的bean定义(合并后的),解析类的元数据时,用到的是ASM技术并不会真正开始解析class文件,所以也只是提取出来bean的name值作为beanClass属性,知道这个前提,那么这一步就好说了,下面是他的源码:- @Override
- protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
- throws BeanCreationException {
- RootBeanDefinition mbdToUse = mbd;
-
- // 马上就要实例化Bean了,确保beanClass被加载了
- Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
- if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
- mbdToUse = new RootBeanDefinition(mbd);
- mbdToUse.setBeanClass(resolvedClass);
- }
- // Prepare method overrides.
- try {
- mbdToUse.prepareMethodOverrides();
- }
- try {
- // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
- // 实例化前
- Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
- if (bean != null) {
- return bean;
- }
- }
- try {
- Object beanInstance = doCreateBean(beanName, mbdToUse, args);
- ......
- return beanInstance;
- }
- }
复制代码
- resolveBeanClass:真正的开始加载bean。
- mbdToUse.prepareMethodOverrides();和@lookUp注解有关系,不看
- resolveBeforeInstantiation:实例化前的BeanPostProcessors,如果初始化了那么就返回了,不走其他创建逻辑了。
- doCreateBean:正常开始实例化、初始化bean。
resolveBeanClass
如果当前bean被加载了,那么直接返回了,如果没加载那么开始解析当前bean- @Nullable
- protected Class<?> resolveBeanClass(RootBeanDefinition mbd, String beanName, Class<?>... typesToMatch)
- throws CannotLoadBeanClassException {
- try {
- // 如果beanClass被加载了
- if (mbd.hasBeanClass()) {
- return mbd.getBeanClass();
- }
- // 如果beanClass没有被加载
- if (System.getSecurityManager() != null) {
- return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>)
- () -> doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
- }
- else {
- return doResolveBeanClass(mbd, typesToMatch);
- }
- }
- }
复制代码 通过这一步也可以看出bean定义中最初的beanClass属性,都是String类型的beanname
resolveBeforeInstantiation
这一步走的是实例化前的工作,当然如果你想在这一步中直接返回实体类也可,而且最离谱的是Spring并没有校验你返回的类是否是当前beanname的类,可以看下源码:- public boolean hasBeanClass() {
- return (this.beanClass instanceof Class);
- }
复制代码
- hasInstantiationAwareBeanPostProcessors:直接从缓存list中获取有关实例化的BeanPostProcessors,这里是一个优化,要不然每次获取有关实例化的BeanPostProcessors都是遍历整个BeanPostProcessors再加个校验
- determineTargetType:获取类
- applyBeanPostProcessorsBeforeInstantiation:执行InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation的方法,该方法可以返回bean。
- postProcessAfterInstantiation:执行BeanPostProcessor的postProcessAfterInstantiation的方法,正常我们的bean不会走到这里,因为实例化前根本没有创建出来bean,所以也就是bean != null一直为false
当然除非你自己写一个InstantiationAwareBeanPostProcessors,其实真没看见这么玩的,主要是没有啥意义,比如这样:- @Nullable
- private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch)
- throws ClassNotFoundException {
- ClassLoader beanClassLoader = getBeanClassLoader();
- ClassLoader dynamicLoader = beanClassLoader;
- boolean freshResolve = false;
- if (!ObjectUtils.isEmpty(typesToMatch)) {
- // When just doing type checks (i.e. not creating an actual instance yet),
- // use the specified temporary class loader (e.g. in a weaving scenario).
- ClassLoader tempClassLoader = getTempClassLoader();
- if (tempClassLoader != null) {
- dynamicLoader = tempClassLoader;
- freshResolve = true;
- if (tempClassLoader instanceof DecoratingClassLoader) {
- DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;
- for (Class<?> typeToMatch : typesToMatch) {
- dcl.excludeClass(typeToMatch.getName());
- }
- }
- }
- }
- String className = mbd.getBeanClassName();
- if (className != null) {
- // 解析Spring表达式,有可能直接返回了一个Class对象
- Object evaluated = evaluateBeanDefinitionString(className, mbd);
- if (!className.equals(evaluated)) {
- // A dynamically resolved expression, supported as of 4.2...
- if (evaluated instanceof Class) {
- return (Class<?>) evaluated;
- }
- else if (evaluated instanceof String) {
- className = (String) evaluated;
- freshResolve = true;
- }
- else {
- throw new IllegalStateException("Invalid class name expression result: " + evaluated);
- }
- }
- if (freshResolve) {
- // When resolving against a temporary class loader, exit early in order
- // to avoid storing the resolved Class in the bean definition.
- if (dynamicLoader != null) {
- try {
- return dynamicLoader.loadClass(className);
- }
- catch (ClassNotFoundException ex) {
- if (logger.isTraceEnabled()) {
- logger.trace("Could not load class [" + className + "] from " + dynamicLoader + ": " + ex);
- }
- }
- }
- return ClassUtils.forName(className, dynamicLoader);
- }
- }
- // Resolve regularly, caching the result in the BeanDefinition...
- return mbd.resolveBeanClass(beanClassLoader);
- }
复制代码 再坚持一下,让我把实例化过程先讲完!
现在的逻辑已经走完了实例化前的postProcessBeforeInstantiation方法,那么现在我们的bean要进行实例化了,- @Nullable
- public static ClassLoader getDefaultClassLoader() {
- ClassLoader cl = null;
- // 优先获取线程中的类加载器
- try {
- cl = Thread.currentThread().getContextClassLoader();
- }
- catch (Throwable ex) {
- // Cannot access thread context ClassLoader - falling back...
- }
- // 线程中类加载器为null的情况下,获取加载ClassUtils类的类加载器
- if (cl == null) {
- // No thread context class loader -> use class loader of this class.
- cl = ClassUtils.class.getClassLoader();
- if (cl == null) {
- // getClassLoader() returning null indicates the bootstrap ClassLoader
- // 加入ClassUtils是被Bootstrap类加载器加载的,则获取系统类加载器
- try {
- cl = ClassLoader.getSystemClassLoader();
- }
- catch (Throwable ex) {
- // Cannot access system ClassLoader - oh well, maybe the caller can live with null...
- }
- }
- }
- return cl;
- }
复制代码 跟这篇无关的内容能删除的都删除了,主要有这几步我们需要注意下:
- createBeanInstance:创建实例,前提是之前没有创建过
- applyMergedBeanDefinitionPostProcessors:找到注入点,比如AutowiredAnnotationBeanPostProcessor(@Autowired、@Value、@Inject)和CommonAnnotationBeanPostProcessor(@Resource),这在实例化前和实例化后方法中间夹了一个处理合并bean定义的逻辑,注意一下
- addSingletonFactory:添加缓存,用来解决循环依赖,以后单独讲解
- populateBean:这一方法主要是属性填充也就是依赖注入的,但是官方把实例化后的PostProcessors方法写到这里了,所以也得贴出来,但是我们只看实例化相关的。
createBeanInstance
- public Class<?> resolveBeanClass(@Nullable ClassLoader classLoader) throws ClassNotFoundException {
- String className = getBeanClassName();
- if (className == null) {
- return null;
- }
- Class<?> resolvedClass = ClassUtils.forName(className, classLoader);
- this.beanClass = resolvedClass;
- return resolvedClass;
- }
复制代码
- resolveBeanClass:之前讲解过了,不重复讲了,就是拿到class
- obtainFromSupplier:通过Supplier函数获取bean,前提是你得声明bean定义
- instantiateUsingFactoryMethod:这种是使用@Bean方法实例化对象,
- 后面省略了推断构造方法进行实例化对象,以后单独讲解推断构造方法
obtainFromSupplier
这一步其实我们用到的很少,主要是考虑到Spring自动注入的开销,我们自己可以就行实例化而已,比如我们这样写照样可以获取bean,但是不会由Spring帮我们注入,得靠自己了:- public String getBeanClassName() {
- Object beanClassObject = this.beanClass;
- if (beanClassObject instanceof Class) {
- return ((Class<?>) beanClassObject).getName();
- }
- else {
- return (String) beanClassObject;
- }
- }
复制代码 其实用法和@bean注解相似,除了减少Spring自动注入的开销,实在没想到有啥用
instantiateUsingFactoryMethod
该方法内部逻辑很多,为了更加直观的展现,只贴出关键代码:- @Nullable
- protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
- Object bean = null;
- if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
- // Make sure bean class is actually resolved at this point.
- // synthetic表示合成,如果某些Bean式合成的,那么则不会经过BeanPostProcessor的处理
- 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;
- }
复制代码 比如我们定义的配置类中有很多@Bean形式的方法,最终Spring会直接invoke调用被@Bean修饰的方法从而实现实例化对象。
applyMergedBeanDefinitionPostProcessors
这里关于MergedBeanDefinitionPostProcessors的实现类不全讲解了,主要讲解下工作常用的注解AutowiredAnnotationBeanPostProcessor,他是用来解析@Autowired、@Value、@Inject,看下他的默认源码:
[code]public AutowiredAnnotationBeanPostProcessor() { this.autowiredAnnotationTypes.add(Autowired.class); this.autowiredAnnotationTypes.add(Value.class); try { this.autowiredAnnotationTypes.add((Class |