spring源码解读

深入了解Spring

Bean

Java bean和spring bean区别

  • Java bean的属性私有,只能通过get和set方法来对属性进行操作。
  • Spring bean是由spring容器生成和管理的对象。

spring Bean的定义方式

  • xml文件 。 声明式。

  • @bean注解。 声明式。

  • @component注解。声明式。

  • @BeanDefinition。编程式

    • AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();
      AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
      beanDefinition.setBeanClass(User.class);
      annotationConfigApplicationContext.registerBeanDefinition("user",beanDefinition);
      annotationConfigApplicationContext.refresh();
      //取出
      User user=annotationConfigApplicationContext.getBean("user",User.class);
      
  • 实现FactoryBean接口

    • 自定义工厂类

      public class ZhuFactoryBean implements FactoryBean {
             
             
          //获取对象
          public Object getObject() throws Exception {
             
             
              Person person=new Person();
              return person;
          }
          //获取类型
          public Class<?> getObjectType() {
             
             
              return Person.class;
          }
      
          public boolean isSingleton() {
             
             
              return false;
          }
      }
      
      
      
      
    • 定义bean和取出bean

      AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();
      AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
      beanDefinition.setBeanClass(ZhuFactoryBean.class);
      //注册工厂类会将工厂类本身添加进入容器,也会将工厂添加的bean注入容器
      annotationConfigApplicationContext.registerBeanDefinition("person",beanDefinition);
      annotationConfigApplicationContext.refresh();
      //取出工厂类
      ZhuFactoryBean zhuFactoryBean=annotationConfigApplicationContext.getBean("&person",ZhuFactoryBean.class);
      //取出工厂定义的bean
      Person person=annotationConfigApplicationContext.getBean("person",Person.class);
      System.out.println(zhuFactoryBean);
      System.out.println(person);
      
  • 使用supplier定义bean

    • annotationConfigApplicationContext.registerBean(User.class, new Supplier<User>() {
             
             
          @Override
          public User get() {
             
             
              User user=new User();
              user.setAge(11);
              return user;
          }
      });
      

spring容器

单例池

  • spring中单例池存放的是单例bean,内部数据结构为concurrentHashMap,spring源码中的定义为Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256)。map的key为name,value为bean对象。它用于保存非懒加载的单例Bean。如果对象使用了AOP完成了一些操作,那么放入单例池的就是代理对象而不是他本身。

Bean生命周期

思维导图

  • 简单来说:

preview

流程总结

通过BeanDefinitionReader接口将xml或者注解配置的对象转换成BeanFactory中的beanDefinitionMap中的beanDefination。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ldqJlZOb-1685347461590)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210718114056465.png)]**—>之后beanFactoryPostProcessor接口的postprocessorFactoryBean方法可以获取到对factoryBean的信息,也就能对beanDefination进行一些操作,例如对xml文件中的占位符进行拼接、对注解的扫描(例如@component修饰的类转化为一个beanDefinition对象)。----->**创建对象,过程可以分为下图两步。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YsWWdlRu-1685347461591)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210717191046208.png)]

spring在实例化的时候是采用反射的方式实例化对象的,之后填充属性。**---->**调用Aware接口中的方法(Aware接口可以帮助自定义对象获取容器类对象(ApplicationContext、BeanFactory等),如简单对象通过实现ApplicationContextAware接口,可以让这个对象get到ApplicationContext容器)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1eZvWHet-1685347461592)(C:\Users\Ric\AppData\Local\Temp\企业微信截图_16265793448073.png)]

**---->**在bean创建之前调用before方法,[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PYejt2Df-1685347461592)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210718112814382.png)]之后调用init方法,之后调用after方法(通过beanPostProcessor接口实现AOP,接口的实现类会创建代理对象)。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G87HYqDS-1685347461593)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210718112925284.png)]

**----》**之后就是一个完整的bean对象了。

思维导图:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hLy6FkuI-1685347461593)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210718114858308.png)]

debug spring源码

debug入口

源码地址:https://gitee.com/qurywu/spring_study.git

使用注解的方式创建bean对象,以及取出bean

AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
User user = annotationConfigApplicationContext.getBean(User.class);
user.run();

初始化IOC

创建AnnotationConfigApplicationContext对象和核心方法

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
   
   
    //step1
    this();
    //step2
    this.register(componentClasses);
    //step3
    this.refresh();
}
step1:this()
 public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
        this.beanNameGenerator = AnnotationBeanNameGenerator.INSTANCE;
        this.scopeMetadataResolver = new AnnotationScopeMetadataResolver();
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        Assert.notNull(environment, "Environment must not be null");
        this.registry = registry;
        this.conditionEvaluator = new ConditionEvaluator(registry, environment, (ResourceLoader)null);
        AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }

这段代码是一个构造函数,用于创建一个AnnotatedBeanDefinitionReader对象。AnnotatedBeanDefinitionReader是一个用于读取注解的BeanDefinition的类,它的作用是将注解转换为BeanDefinition对象并注册到BeanDefinitionRegistry中。

在构造函数中,首先设置了beanNameGenerator和scopeMetadataResolver的值,分别用于生成Bean的名称和解析Bean的作用域。然后通过断言确保传入的BeanDefinitionRegistry和Environment对象不为空,接着将它们赋值给成员变量registry和conditionEvaluator。

最后,调用AnnotationConfigUtils.registerAnnotationConfigProcessors方法,该方法会注册一些用于处理注解的BeanPostProcessor,例如AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor等。

step2:this.register(componentClasses)
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier, @Nullable BeanDefinitionCustomizer[] customizers) {
    AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
    if (!this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
        abd.setInstanceSupplier(supplier);
        ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
        abd.setScope(scopeMetadata.getScopeName());
        String beanName = name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry);
        //如果传入了qualifiers参数,则遍历qualifiers数组,根据不同的限定符设置BeanDefinition的Primary、LazyInit或Qualifier属性。
        AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
        int var10;
        int var11;
        if (qualifiers != null) {
            Class[] var9 = qualifiers;
            var10 = qualifiers.length;

            for(var11 = 0; var11 < var10; ++var11) {
                Class<? extends Annotation> qualifier = var9[var11];
                if (Primary.class == qualifier) {
                    abd.setPrimary(true);
                } else if (Lazy.class == qualifier) {
                    abd.setLazyInit(true);
                } else {
                    abd.addQualifier(new AutowireCandidateQualifier(qualifier));
                }
            }
        }

        if (customizers != null) {
            BeanDefinitionCustomizer[] var13 = customizers;
            var10 = customizers.length;

            for(var11 = 0; var11 < var10; ++var11) {
                BeanDefinitionCustomizer customizer = var13[var11];
                customizer.customize(abd);
            }
        }

        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
        definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
        BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
    }
}

这段代码是一个私有方法,用于注册一个BeanDefinition。该方法接收一个beanClass参数,表示要注册的Bean的类型;一个name参数,表示Bean的名称;一个qualifiers参数,表示Bean的限定符;一个supplier参数,表示Bean的实例提供者;一个customizers参数,表示BeanDefinition的自定义器。

在方法中,首先创建一个AnnotatedGenericBeanDefinition对象,并通过conditionEvaluator判断是否应该跳过该BeanDefinition。然后设置BeanDefinition的实例提供者和作用域,并根据传入的name或使用beanNameGenerator生成Bean的名称。接着调用AnnotationConfigUtils.processCommonDefinitionAnnotations方法处理BeanDefinition上的常见注解。

如果传入了qualifiers参数,则遍历qualifiers数组,根据不同的限定符设置BeanDefinition的Primary、LazyInit或Qualifier属性。如果传入了customizers参数,则遍历customizers数组,调用每个BeanDefinitionCustomizer的customize方法对BeanDefinition进行自定义。

最后,将BeanDefinition封装为BeanDefinitionHolder对象,并根据作用域设置代理模式,最终通过BeanDefinitionReaderUtils.registerBeanDefinition方法将BeanDefinition注册到BeanDefinitionRegistry中。

register的实质是注册到BeanDefinitionMap中

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
   
   
    Assert.hasText(beanName, "Bean name must not be empty");
    Assert.notNull(beanDefinition, "BeanDefinition must not be null");
    if (beanDefinition instanceof AbstractBeanDefinition) {
   
   
        try {
   
   
        	//beanDefinition校验
            ((AbstractBeanDefinition)beanDefinition).validate();
        } catch (BeanDefinitionValidationException var8) {
   
   
            throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var8);
        }
    }
	//通过那么从beanDefinitionMap中拿到BeanDefinition
    BeanDefinition existingDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
    //判断BeanDefinitionRegistry中是否已经存在同名的BeanDefinition对象。如果存在,则根据isAllowBeanDefinitionOverriding方法的返回值决定是否允许覆盖原有的BeanDefinition对象。如果允许覆盖,则根据BeanDefinition对象的角色和内容进行判断,如果需要覆盖则进行覆盖操作,否则不进行任何操作。
    if (existingDefinition != null) {
   
   
        if (!this.isAllowBeanDefinitionOverriding()) {
   
   
            throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
        }

        if (existingDefinition.getRole() < beanDefinition.getRole()) {
   
   
            if (this.logger.isInfoEnabled()) {
   
   
                this.logger.info("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
            }
        } else if (!beanDefinition.equals(existingDefinition)) {
   
   
            if (this.logger.isDebugEnabled()) {
   
   
                this.logger.debug("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
            }
        } else if (this.logger.isTraceEnabled()) {
   
   
            this.logger.trace("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
        }

        this.beanDefinitionMap.put(beanName, beanDefinition);
    } else {
   
   
    //如果不存在同名的BeanDefinition对象,则将BeanDefinition对象添加到BeanDefinitionRegistry中,并更新BeanDefinitionRegistry中的Bean名称列表。如果BeanDefinitionRegistry已经开始创建Bean,则需要进行同步操作
        if (this.hasBeanCreationStarted()) {
   
   
            synchronized
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值