Spring组件分析

其实这篇博文写的很粗糙,主要是记录一下分析源码的过程,我觉得最重要的还是用debug去跟一次

对象从创建到注入到容器的过程,Spring做了什么事。

其实做了蛮多事的,有的基本上看不懂。

其实也可以借鉴组件化思想,Spring是个IOC容器,我们注入的对象就是组件

而组件就存在生命周期,初始化和销毁,以及相互继承和引用等关系。

两大图,图片来自于

https://javadoop.com/post/spring-ioc#BeanFactory%20%E7%AE%80%E4%BB%8B

 

BeanFactory 管理容器中所有bean的工厂

 

Object getBean(String name) throws BeansException;

获得注册好的bean对象

boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

是否是单例对象

NoSuchBeanDefinitionException这个异常恐怕是耳闻熟详,

一般情况就是容器中不存在这个bean,而你使用配置文件或者注解将它注入,导致找不到这个bean 。或者是单例模式下存在不唯一的bean

 

ListableBeanFactory 列出所有在容器中注册的bean

获取到所有在容器中注册的bean的名称

String[] getBeanDefinitionNames();

获取指定注解所有的 Bean 的名称

String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType);

获取到指定注解的所有bean的集合

Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) throws BeansException;

总而言之这个接口实现按照不同条件获取bean名称或者bean集合功能的

HierarchicalBeanFactory 分层 bean工厂接口

获得父级bean工厂

BeanFactory getParentBeanFactory();

通过bean名称判断本地bean工厂是否包含该bean对象

boolean containsLocalBean(String name);

总而言之,这个接口就是对多个bean工厂设置父子关系,实现分层的功能

AutowireCapableBeanFactory自动装配bean工厂

根据类对象创建对应的bean对象(创建bean对象的实例)

<T> T createBean(Class<T> beanClass) throws BeansException;

将已存在的bean对象自动装配到容器中

void autowireBean(Object existingBean) throws BeansException;

这里我补充一下,我们传统程序设计,A对象需要用到B对象,都是直接在A类中直接new B对象,这就造成耦合,而IOC容器就是帮我们解决这个问题,所有对象的创建都由IOC完成,我们只需要配置一下就可以使用了,无非就是xml配置文件和注解方式进行注入。

这两个方法应该就是实现该过程的一部分。

自动装配bean

Object configureBean(Object existingBean, String beanName) throws BeansException;

这个方法估计就是@Configuration和@Bean注解的实现了。

初始化bean对象

Object initializeBean(Object existingBean, String beanName) throws BeansException;

bean对象之前做一些事情

Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
      throws BeansException;

bean对象初始化之后做一些事

Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
      throws BeansException;

ApplicationContext上下文对象,重点中的重点

为什么它这么牛逼?

继承了这么接口,你说功能丰不丰富

EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver

对于想要拥有自动装配能力,并且想把这种能力暴露给外部应用的BeanFactory类需要实现此接口。 
正常情况下,不要使用此接口,应该更倾向于使用BeanFactory或者ListableBeanFactory接口。此接口主要是针对框架之外,没有向Spring托管Bean的应用。通过暴露此功能,Spring框架之外的程序,具有自动装配等Spring的功能

AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;

ConfigurableBeanFactory 可配置的bean工厂

配置bean对象的作用域

String SCOPE_SINGLETON = "singleton";

String SCOPE_PROTOTYPE = "prototype";

设置类的加载类,用来加载类。

void setBeanClassLoader(ClassLoader beanClassLoader);

返回该bean对象的加载类

ClassLoader getBeanClassLoader();

添加一个用于处理bean组件初始化之前或者之后操作的后置处理器

void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);

 

AbstractBeanFactory 抽象bean工厂

 

一看这么多就知道这个抽象类功能是有多么丰富了。。

说几个重要的方法

首先这个方法熟悉的不能再熟悉了吧,通过名称获取bean对象(单例)

@Override
public Object getBean(String name) throws BeansException {
   return doGetBean(name, null, null, false);
}

通过id名称和类型来获取bean对象

@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
   return doGetBean(name, requiredType, null, false);
}

这个方法就比较重要了,自己跟着源码走一波吧。。

其实就是获取bean对象的过程,要经过一系列的校验和判断

protected <T> T doGetBean(
      final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
      throws BeansException

创建bean对象才是核心方法,实现原理是java反射。

protected abstract Object createBean(String beanName, RootBeanDefinition mbd, Object[] args)
      throws BeanCreationException;

我反正跟着跟着就跟崩了。。

AbstractAutowireCapableBeanFactory

抽象自动装配bean工厂

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
      implements AutowireCapableBeanFactory

也就是AbstractBeanFactory和AutowireCapableBeanFactory的综合实现

这些方法都是用来创建和填充类的实例

@Override
@SuppressWarnings("unchecked")
public <T> T createBean(Class<T> beanClass) throws BeansException {
   // Use prototype bean definition, to avoid registering bean as dependent bean.

使用原型bean定义,避免将bean注册为依赖bean

就是我们可能存在这么一种情况,当需要两个bean相互协作时,例如beanA是beanB的属性,那么当bean的生命周期不同时,就容易出现问题

不过这段代码是实现多例模式下创建bean的过程,返回的应该是bean的类而不是bean的一个实例。
   RootBeanDefinition bd = new RootBeanDefinition(beanClass);
   bd.setScope(SCOPE_PROTOTYPE);
   bd.allowCaching = ClassUtils.isCacheSafe(beanClass, getBeanClassLoader());
   return (T) createBean(beanClass.getName(), bd, null);
}

@Override
public void autowireBean(Object existingBean) {
   // Use non-singleton bean definition, to avoid registering bean as dependent bean.

使用非单例bean定义,避免注册为依赖bean
   RootBeanDefinition bd = new RootBeanDefinition(ClassUtils.getUserClass(existingBean));
   bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
   bd.allowCaching = ClassUtils.isCacheSafe(bd.getBeanClass(), getBeanClassLoader());
   BeanWrapper bw = new BeanWrapperImpl(existingBean);
   initBeanWrapper(bw);
   populateBean(bd.getBeanClass().getName(), bd, bw);
}

@Override
public Object configureBean(Object existingBean, String beanName) throws BeansException {
   markBeanAsCreated(beanName);
   BeanDefinition mbd = getMergedBeanDefinition(beanName);
   RootBeanDefinition bd = null;
   if (mbd instanceof RootBeanDefinition) {
      RootBeanDefinition rbd = (RootBeanDefinition) mbd;
      bd = (rbd.isPrototype() ? rbd : rbd.cloneBeanDefinition());
   }
   if (!mbd.isPrototype()) {
      if (bd == null) {
         bd = new RootBeanDefinition(mbd);
      }
      bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
      bd.allowCaching = ClassUtils.isCacheSafe(ClassUtils.getUserClass(existingBean), getBeanClassLoader());
   }
   BeanWrapper bw = new BeanWrapperImpl(existingBean);
   initBeanWrapper(bw);
   populateBean(beanName, bd, bw);
   return initializeBean(beanName, existingBean, bd);
}

跟一波源码吧

ConfigurableListableBeanFactory

配置列出所有bean的工厂接口

说白了就是注解实现方式,加上自身的8个方法,一共有83个方法实现,

public interface ConfigurableListableBeanFactory
      extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory {

 

根据bean的名称返回bean的定义

BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

@Override
public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
   BeanDefinition bd = this.beanDefinitionMap.get(beanName);
   if (bd == null) {
      if (logger.isTraceEnabled()) {
         logger.trace("No bean named '" + beanName + "' found in " + this);
      }
      throw new NoSuchBeanDefinitionException(beanName);
   }
   return bd;
}

private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);

ConcurrentHashMap这个map关注一下,线程安全

 

DefaultListableBeanFactory默认可列出所有bean的工厂类

这个类可以说是最最最常见的类

https://blog.csdn.net/pengjx2014/article/details/83045333#DefaultListableBeanFactory_1

具体内容见这篇文档,不过你看了基本上也不会想看第二遍了。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值