【Spring源码解析】SpringIOC(1)—— Bean与BeanDefinition

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 全局视角看核心接口和类Bean与BeanDefinitionBeanDefinition是Bean的定义容器初始化主要做的事情(主要脉络)BeanDefinition源码

全局视角看核心接口和类


解决了关键的问题:将对象之间的关系转而用配置来管理


依赖注入 —— 依赖关系在Spring的loC容器中管理


通过把对象包装在Bean中以达到管理对象和进行额外操作的目的


Bean与BeanDefinition

Bean是Spring的一等公民:


Bean的本质就是java对象,只是这个对象的生命周期由容器来管理

不需要为了创建Bean而在原来的java类上添加任何额外的限制

对java对象的控制方式体现在配置上


BeanDefinition是Bean的定义


根据配置,生成用来描述Bean的BeanDefinition,常用属性如下:


jdk中使用java.lang.class来描述这个对象,spring使用BeanDefinition来描述bean


作用范围 scope(@Scope)

懒加载 lazy-init(@Lazy):决定Bean实例是否延迟加载

首选primary(@Primary):设置为true的bean会是优先的实现类

一个接口对应多个实现bean的情况下,使用这个注解的接口会被优先实现

factory-bean 和 factory-method(@Configuration和@Bean)

无参构造方法创建bean的演示:


在项目中创建一个entity包,并创建一个User类


package com.wjw.entity;
public class User {
}

此时在xml中定义相应的bean可以使用无参的构造方法来实现


<bean id="user1" class="com.wjw.entity.User" scope="singleton" lazy-init="true" primary="true"/>


使用静态工厂创建bean演示:

再创建一个静态工厂类

package com.wjw.entity.factory;
import com.wjw.entity.User;
public class StaticFactory {
   public static User getUser(){
      return new User();
   }
}

此时在xml中定义相应的bean可以使用静态工厂方法来实现

<!-- class的值不是写User对象的全路径,而是写静态工厂的全路径 -->
<!-- factory-method的值写要调用的方法 -->
<bean id="user2" class="com.wjw.entity.factory.StaticFactory" factory-method="getUser" scope="singleton"/>


使用实例工厂创建bean示例:


package com.wjw.entity.factory;
import com.wjw.entity.User;
public class UserFactory {
   public User getUser(){
      return new User();
   }
}


由于方法不是静态的,所以不能直接调用,只能先创建一个工厂的对象,然后通过对象再进行调用


<!-- 需要先创建factoryBean对象,再通过factoryBean对象进行调用 -->
<bean id="userFactory" class="com.wjw.entity.factory.UserFactory"/>
<bean id="user3" factory-bean="userFactory" factory-method="getUser" scope="singleton" />


测试:


package com.wjw;
import com.wjw.controller.WelcomeController;
import com.wjw.entity.User;
import com.wjw.service.WelcomeService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.FileSystemXmlApplicationContext;
@Configuration
@ComponentScan("com.wjw")
public class Entrance {
   public static void main(String[] args) {
      System.out.println("Hello World!");
      String xmlPath = "F:\\Java\\spring-framework-5.2.0.RELEASE\\springdemo\\src\\main\\resources\\spring\\spring-config.xml";
      ApplicationContext applicationContext = new FileSystemXmlApplicationContext(xmlPath);
      WelcomeService welcomeService = (WelcomeService) applicationContext.getBean("welcomeService");
      welcomeService.sayHello("强大的spring框架");
      //得到无参构造函数创建的对象:
      User user1a = (User) applicationContext.getBean("user1");
      User user1b = (User) applicationContext.getBean("user1");
      //得到静态工厂创建的对象:
      User user2a = (User) applicationContext.getBean("user2");
      User user2c = (User) applicationContext.getBean("user2");
      //得到实例工厂创建的对象:
      User user3a = (User) applicationContext.getBean("user3");
      User user3b = (User) applicationContext.getBean("user3");
      System.out.println("无参构造函数创建的对象:" + user1a);
      System.out.println("无参构造函数创建的对象:" + user1b);
      System.out.println("静态工厂创建的对象:" + user2a);
      System.out.println("静态工厂创建的对象:" + user2c);
      System.out.println("实例工厂创建的对象:" + user3a);
      System.out.println("实例工厂创建的对象:" + user3b);
   }
}


17.png


容器初始化主要做的事情(主要脉络)


18.png


BeanDefinition源码


19.png


20.png

继承了两个接口,spring中充斥着大量接口,继承某个接口就意味着具有某一项功能。


AttributeAccessor定义了最基本的对任意对象元数据的修改或者获取方式,用在这里主要就是为了获取BeanDefinition的属性,并操作这些属性。


BeanMetadataElement主要定义了一个getSource方法,用于返回一个可配置的源对象,用在这里主要就是为了返回BeanDefinition对象本身。


AttributeAccessorSupport是AttributeAccessor的实现类。


AbstractBeanDefinition是BeanDefinition实现类的基类,定义了一些初始化通用属性的构造函数,以及对应的getter和setter,还有一些操作的通用方法。基于AbstractBeanDefinition抽象类,spring实现了一些有特殊用途的BeanDefinition。


RootBeanDefinition可以单独作为BeanDefinition,也可以作为其他BeanDefinition的父类,但不能作为其他的子类。(通常用来在运行时接收多个BeanDefinition合并起来的信息,可以接收具有继承关系的多个BeanDefinition,承接他们合并在一起的除了parent属性以外的属性)。一般情况下,配置文件里的bean标签会被解析成为RootBeanDefinition,但spring2.5之后使用GenericBeanDefinition来代替了,但因为先前的根基,所以在合并BeanDefinition时还是会用RootBeanDefinition来接收。


21.png

ps:spring中的继承是通过设置parent属性来决定的,不是extends


ChildBeanDefinition 已经被取代了。

GenericBeanDefinition(bean文件配置属性定义类)除了具有BeanDefinition属性之外还有parent属性,方便程序运行时去设定parent BeanDefinition,不会报异常,是一种更好的方案。


相关文章
|
13天前
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
|
12天前
|
存储 Java Spring
【Spring】获取Bean对象需要哪些注解
@Conntroller,@Service,@Repository,@Component,@Configuration,关于Bean对象的五个常用注解
|
12天前
|
存储 Java 应用服务中间件
【Spring】IoC和DI,控制反转,Bean对象的获取方式
IoC,DI,控制反转容器,Bean的基本常识,类注解@Controller,获取Bean对象的常用三种方式
|
18天前
|
XML Java 数据格式
Spring容器Bean之XML配置方式
通过对以上内容的掌握,开发人员可以灵活地使用Spring的XML配置方式来管理应用程序的Bean,提高代码的模块化和可维护性。
54 6
|
19天前
|
XML Java 数据格式
🌱 深入Spring的心脏:Bean配置的艺术与实践 🌟
本文深入探讨了Spring框架中Bean配置的奥秘,从基本概念到XML配置文件的使用,再到静态工厂方式实例化Bean的详细步骤,通过实际代码示例帮助读者更好地理解和应用Spring的Bean配置。希望对你的Spring开发之旅有所助益。
83 3
|
1月前
|
安全 Java 开发者
Spring容器中的bean是线程安全的吗?
Spring容器中的bean默认为单例模式,多线程环境下若操作共享成员变量,易引发线程安全问题。Spring未对单例bean做线程安全处理,需开发者自行解决。通常,Spring bean(如Controller、Service、Dao)无状态变化,故多为线程安全。若涉及线程安全问题,可通过编码或设置bean作用域为prototype解决。
34 1
|
8月前
|
Java 关系型数据库 数据库连接
Spring源码解析--深入Spring事务原理
本文将带领大家领略Spring事务的风采,Spring事务是我们在日常开发中经常会遇到的,也是各种大小面试中的高频题,希望通过本文,能让大家对Spring事务有个深入的了解,无论开发还是面试,都不会让Spring事务成为拦路虎。
108 1
|
3月前
|
Java Spring
Spring底层架构源码解析(三)
Spring底层架构源码解析(三)
196 5
|
3月前
|
XML Java 数据格式
Spring底层架构源码解析(二)
Spring底层架构源码解析(二)
|
3月前
|
Java Spring 容器
Spring IOC、AOP与事务管理底层原理及源码解析
【10月更文挑战第1天】Spring框架以其强大的控制反转(IOC)和面向切面编程(AOP)功能,成为Java企业级开发中的首选框架。本文将深入探讨Spring IOC和AOP的底层原理,并通过源码解析来揭示其实现机制。同时,我们还将探讨Spring事务管理的核心原理,并给出相应的源码示例。
153 9

热门文章

最新文章