`
songzi0206
  • 浏览: 158813 次
  • 性别: Icon_minigender_1
  • 来自: 上海
博客专栏
Group-logo
All are from ...
浏览量:33810
Group-logo
Programming w...
浏览量:19678
社区版块
存档分类
最新评论
阅读更多

      做过不少项目,用到最多的框架当属 Spring 了,但是至今都没有去整理过任何一篇关于 Spring 学习的文档:一是因为 Reference 比较详细,平时项目中基本上都能查到;二是因为有很多关于 Spring 的文章都写的相当好,觉得没有必要自己再写。今天我鼓起勇气整理一篇关于 BeanFactory 相关的文章,算是自己对 Spring Ioc 学习的一归纳,学习笔记嘛,否则,读过代码在记忆停留的时间总是那么有限。

    BeanFactory ,作为 Spring 基础的 IoC 容器,从名字上看就是 Spring 的一个 Bean 工厂。如果单从工厂模式的角度思考,它就是用来“生产 Bean ”,然后提供给客户端。但是它到底是如何生产 Bean 的呢?生产 Bean 的“原料”获取、解析、以及 Bean 之间的依赖是如何完成的呢?这并不没有想象中的那么简单。直接来看最基础的 BeanFactory 类图吧:

     在细看类图之前,先弄清 IOC 的流程。回想我们平时使用,大多数时候只是配置一下,就可以直接使用 Spring IOC 了,这其中必然需要读取配置、解析配置、生产 Bean 、将 Bean 注册到一个统一的地方提供客户端获取使用。暂不考虑配置的读取和解析,来看 spring 的接口功能的定义:

 

1.          首先是顶层的 BeanFactory ,从他定义的方法看,主要提供获 Bean 对象,判断给定的 Bean 对象是否被当前的 BeanFactory 加载过、是否是 Singleton/Prototype 、类型是否匹配,等等最最基本,也是客户端最最需要使用的功能 ( 如果不是为了学习,客户端才不会关心你的 bean 是怎么来的,反正我只要能调用完成自己的功能就 ok )

2.        左边分支:也就是 ListableBeanfactory ,此接口继承了 BeanFactory 的同时,提供了列举 Bean 的功能,他能够列举当前 BeanFactory 加载的所有 Bean :列举所有 Bean 的名字或者满足某种类型的 Bean 的名字,根据类型返回所有 Bean 对象 , 等。但是它无法获取上层 BeanFactory 加载的单例 Bean

3.        看中间分支: HierachicalBeanFactory ConfigurableBeanFactory HierarchicalBeanFactory 比较简单,它主要是提供父 BeanFactory 的功能,通过它能够获取当前 BeanFactory 的父工厂( PS: 若在 A 工厂启动并加载 Bean 之前, B 工厂先启动并加载了,那 B 就是 A 的父工厂),这样就能让当前的 BeanFactory 加载父工厂加载的 Bean 了,弥补了 ListableBeanfactory 欠缺的功能。 ConfigurableBeanFactory 就是在 HierarchicalBeanFactory 的基础上增加了可配置的功能,包括注册别名、注册单例等,设置 Classloader 、是否缓存 Bean Metadata 、设置 TypeConverter BeanPostProcessor 、配置 Bean 依赖等。 PS:ConfigurableBeanFactory 还继承了 SingletonBeanRegistry 接口主要是用来定义为用来共享的 bean 实例的注册表,通过它可以使得 BeanFactory 实现统一的方式暴露其单例 bean 管理。

4.        再看右边分支:该分支分两块――

      首先是 AutowireCapableBeanFactory ,主要是提供自动 Bean 自动绑定 ( 或者说自动装配 ) 功能。例如根据自动装配策略 new 一个 bean ,为已有的 bean 装配属性依赖;还有创建 bean 之后的回调功能,为 bean 设置 name bean factory bean post processor 等;将 bean post processor 应用到 bean 的初始化,等等。    其次 SingletonBeanRegistry/DefaultSingletonBeanRegistry/FactoryBeanRegistrySupport SingletonBeanRegistry 在前面已提到, DefaultSingletonBeanRegistry 是它的默认实现类,它不仅支持 Singleton Bean 的注册,也支持 DisposableBean 的注册管理用来清理要丢弃的 bean 以及他们依赖的资源。如果去大概看一下代码的话,它主要维护了这些资源:

 

 

/** Cache of singleton objects: bean name --> bean instance */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>();

	/** Cache of singleton factories: bean name --> ObjectFactory */
	private final Map<String, ObjectFactory> singletonFactories = new HashMap<String, ObjectFactory>();

	/** Cache of early singleton objects: bean name --> bean instance */
	private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>();

	/** Set of registered singletons, containing the bean names in registration order */
	private final Set<String> registeredSingletons = new LinkedHashSet<String>(16);

	/** Names of beans that are currently in creation */
	private final Set<String> singletonsCurrentlyInCreation = Collections.synchronizedSet(new HashSet<String>());

	/** List of suppressed Exceptions, available for associating related causes */
	private Set<Exception> suppressedExceptions;

	/** Flag that indicates whether we're currently within destroySingletons */
	private boolean singletonsCurrentlyInDestruction = false;

	/** Disposable bean instances: bean name --> disposable instance */
	private final Map<String, Object> disposableBeans = new LinkedHashMap<String, Object>();

	/** Map between containing bean names: bean name --> Set of bean names that the bean contains */
	private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<String, Set<String>>();

	/** Map between dependent bean names: bean name --> Set of dependent bean names */
	private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<String, Set<String>>();

	/** Map between depending bean names: bean name --> Set of bean names for the bean's dependencies */
	private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<String, Set<String>>();

 

    仔细读一下代码的话,可以看到 Spring 对这些容器的并发、同步的控制,这些都依赖与 Spring Core 以及 JDK

    再说 FactoryBeanRegistrySupport ,主要是对 FactoryBean 的支持, 获取 FactoryBean FactoryBean 的类型、获取 FactoryBean 曝露的目标对象等,而这些功能都是基于附接口对 Bean 的注册功能的。 FactoryBean Spring 提供的一种扩展容器实例化 Bean 逻辑的接口,相信大家都用过类似 ProxyFactoryBean TransactionProxyFactoryBean LocalSessionFactoryBean 等,其实 Spring 和其框架整合的时候都会针对具体框架提供一个 ***FactoryBean 。而 AbstractBeanFactory 既实现了 ConfigurableBeanFactory ,又继承了 FactoryBeanRegistrySupport 的功能。

    最后 AbstractAutoWireCapableBeanFactory ,实现 AutowireCapableBeanFactory 接口的 Bean 装配功能,可参见其实现的 createBean/autowireBean/configureBean 方法,这里就包含了 bean 创建装配的逻辑。以最完整的 createBean 方法为例,来窥探下整个流程:概括的讲先根据 Class 类型包装成 RootBeanDefinition 并设置 SCOPE ,然后调用重载方法 createBean(beanClass.getName(), bd, null) 就完事了。 看这个重载方法:

 

protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
			throws BeanCreationException {

		AccessControlContext acc = AccessController.getContext();
		return AccessController.doPrivileged(new PrivilegedAction() {
			public Object run() {
				if (logger.isDebugEnabled()) {
					logger.debug("Creating instance of bean '" + beanName + "'");
				}
				// Make sure bean class is actually resolved at this point.
				resolveBeanClass(mbd, beanName);

				// Prepare method overrides.
				try {
					mbd.prepareMethodOverrides();
				}
				catch (BeanDefinitionValidationException ex) {
					throw new BeanDefinitionStoreException(mbd.getResourceDescription(),
							beanName, "Validation of method overrides failed", ex);
				}

				try {
					// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
					Object bean = resolveBeforeInstantiation(beanName, mbd);
					if (bean != null) {
						return bean;
					}
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"BeanPostProcessor before instantiation of bean failed", ex);
				}

				Object beanInstance = doCreateBean(beanName, mbd, args);
				if (logger.isDebugEnabled()) {
					logger.debug("Finished creating instance of bean '" + beanName + "'");
				}
				return beanInstance;
			}
		}, acc);
	}

 

 

     参考代码,可将这个过程分为 4 步:

1)       解决 Bean Class 类型

主要用于保证 RootBeanDefinition 具有 Class 信息

2)       处理重写的方法

用来验证重写的方法是否合法,防止将来反射调用报错

3)       resolveBeforeInstantiation

Bean 实例 之前, 容器级别生命周期接口方法调用 InstantiationAwareBeanPostProcessor. postProcessBeforeInstantiation(beanClass, beanName)

4)       调用 doCreateBean(beanName,rbd,args) 方法

 

这个方法就复杂一点了,首先它会包装 BeanWrapper 对象,将 bean 对象包装到一个 BeanWrapper 对象中,然后对 MergedBeanDefinitionPostProcessor 接口的 Bean 进行回调,接着会标识 Singleton Factory( 如果需要的话 ) ,接下来是 populateBean initializeBean 。最后根据 Bean Scope 决定让 Spring 来继续管理其生命周期还是交给客户端来管理, Spring 会为其注册 DisposableBean ,具体参见 registerDisposableBeanIfNecessary(beanName, bean, mbd)

populateBean 可以简单认为是设置 Bean properties ,具体:     

Ø  BeanDefinition 中获取 Properties’ Values

Ø  调用 InstantiationAwareBeanPostProcessor . postProcessAfterInstantiation 方法

Ø  Bean 自动装配处理

Ø  调用 InstantiationAwareBeanPostProcessor . postProcessProperty Values 方法

Ø  依赖检查 ( 如果需要的话 )

Ø  使 Properties Values 生效

 

initializeBean 方法在 Bean properties 生效后执行,具体:

Ø  实现 BeanNameAware bean 设置 beanName

Ø  实现 BeanClassLoaderAware bean 设置 beanClassLoader

Ø  实现 BeanFactoryAware bean 设置 beanFactory

Ø  调用 BeanPostProcessor . postProcess BeforeInitialization 方法,我们在这一步可以对 Bean 对象进行修改

Ø  Invoke init method ,调用 afterPropertiesSet() 或指定的初始化方法

Ø  调用 BeanPostProcessor . postProcess AfterInitialization 方法

      到此,核心的 Bean 生产装配功能都在 AbstractAutowireCapableBeanFactory 实现了,下层的 DefaultListableBeanFactory 继承这些功能的同时再实现可配置的功能 from ConfigurableListableBeanFactory 。另外,它还实现了 BeanDefinitionRegistry 。做为 full fledged BeanFactory DefaultListableBeanFactory 已经可以为客户端使用了,但是需要自己编程使用:

//测试Bean
public class Person {

	String name;
	Address address;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Address getAddress() {
		return address;
	}
	public void setAddress(Address address) {
		this.address = address;
	}
	@Override
	public String toString() {
		return name + "@" + address.getName();
	}
}

public class Address {

	String name;
	public Address(String name){
		this.name = name;
	}
}
//客户端
public class DefaultListableBeanFactoryTest {

	public static void main(String[] args){
		DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
		wireBeans(beanFactory);
		//使用
		Person p = (Person) beanFactory.getBean("newHier");
		System.out.println(p.toString());
	}

	private static BeanFactory wireBeans(BeanDefinitionRegistry registry) {
		RootBeanDefinition personBean = new RootBeanDefinition(Person.class);
		RootBeanDefinition addressBean = new RootBeanDefinition(Address.class);
		
		//将Bean注册到容器
		registry.registerBeanDefinition("newHier", personBean);
		registry.registerBeanDefinition("newHierAddress", addressBean);
		//通过构造方法为addressBean注入属性
		ConstructorArgumentValues argValues = new ConstructorArgumentValues();
		argValues.addIndexedArgumentValue(0, "Shilong Road");
		addressBean.setConstructorArgumentValues(argValues);
		//通过setter为personBean注入属性
		MutablePropertyValues propertiesValues = new MutablePropertyValues();
		propertiesValues.addPropertyValue(new PropertyValue("name","Wilson"));
		propertiesValues.addPropertyValue(new PropertyValue("address",addressBean));
		personBean.setPropertyValues(propertiesValues);
		
		//完成bean注册,返回BeanFactory
		return (BeanFactory)registry;
	}
}

   执行客户端测试,输入Wilson@Shilong Road

 

    作为本文的结尾,简单说两句类图中最底层的XmlBeanFactory,其实就是方便我们用Xml文件来配置,这样就不用那么麻烦的使用DefaultListableBeanFactory编程了。我们可以看到XmlBeanFactory依赖于XmlBeanDefinitionReader,这个Reader就是用来读取并解析Xml配置文件的。

 

 

 

  • 大小: 72.7 KB
分享到:
评论

相关推荐

    实验一 Springioc基本操作.docx

    SpringIOC是Spring Framework中的核心组件之一,负责管理应用程序中的对象、依赖关系和生命周期。 在 Spring IOC 中,对象的创建和管理是通过 BeanFactory 或 ApplicationContext 实现的。BeanFactory 是 Spring ...

    Spring IoC加载流程讲解

    Spring IoC 加载流程讲解 在本节中,我们将对 Spring IoC 加载流程进行详细的讲解,并探讨 IoC 思想和依赖倒置原则的应用。 IoC 控制反转 IoC(Inversion of Control)是指在软件设计中,将对象实例的控制权从...

    spring ioc思维导图源文件

    Spring IOC(Inversion of Control,控制反转)是Spring框架的核心特性之一,它允许开发者将对象的创建和管理交给Spring容器来处理,从而使代码更加松耦合,更易于测试和维护。下面将详细介绍Spring IOC的基本概念、...

    spring ioc

    Spring 是一个广泛应用的 Java 应用开发框架,其核心特性之一就是IOC,它极大地简化了软件组件之间的依赖管理。在本文中,我们将深入探讨 Spring IOC 的概念、工作原理以及如何在实际项目中应用。 首先,理解 IOC ...

    Spring IoC源码深度剖析开源架构源码2021.pdf

    - `BeanFactory` 是Spring IoC容器的顶层接口,代表了IoC容器的基础原则和能力。其不能被实例化,提供了一套IoC容器必须遵循的基本原则。 - `ApplicationContext` 是在 `BeanFactory` 的基础上,添加了更多功能的...

    Spring IOC.pdf

    Spring IOC,即Spring控制反转,是Spring框架的核心特性之一。控制反转(Inversion of Control,简称IoC)是一种设计原则,用于减少代码间的耦合,提高系统模块化和代码的重用性。在Spring框架中,IOC具体体现在对...

    Spring IOC容器实现分析.pdf 下载

    在Java开发领域,Spring框架无疑是使用最为广泛的轻量级框架之一,其中的核心组件就是IOC(Inversion of Control)容器。本文将深入剖析Spring的IOC容器,理解其工作原理和重要功能,以帮助开发者更好地利用这一强大...

    Spring的IoC容器之BeanFactory[定义].pdf

    Spring的IoC容器是其核心特性之一,它通过BeanFactory和ApplicationContext两个主要接口来实现控制反转(Inversion of Control,IoC)的概念。BeanFactory作为基础的IoC容器,提供了全面的IoC服务,包括对象的注册、...

    Spring IOC源码解读

    Spring IOC,即Inversion of Control(控制反转),是Spring框架的核心特性之一,它负责管理和装配应用程序中的对象。在传统的编程模式中,对象通常自行创建和管理它们所依赖的其他对象,这导致了代码间的高耦合。而...

    Spring ioc源码解读

    Spring框架的核心功能之一便是依赖注入(Dependency Injection, DI),而这一功能主要通过IoC容器来实现。在Spring框架中,IoC容器负责管理应用对象的生命周期、配置和装配。简单来说,IoC容器就是一个工厂,它可以...

    手写spring ioc(三) 资源org.zip

    在本资源"手写spring ioc(三) 资源org.zip"中,我们主要关注的是如何实现一个简易版的Spring IOC(Inversion of Control)容器,它涵盖了ioc的基本功能,包括解决循环依赖、使用构造器注入以及自动注入等核心特性。...

    Spring-ioc-jar

    Spring IOC,全称为Inversion of Control,中文常被称为“控制反转”,是Spring框架的核心特性之一。这个概念在软件设计中引入了一种新的依赖管理方式,它将对象的创建和管理权交给了容器,使得开发者可以更专注于...

    Spring IOC基础jar包

    `BeanFactory`接口和它的实现类如`DefaultListableBeanFactory`都在这个包中,它们是IOC容器的基础。 3. `org.springframework.core-3.0.6.RELEASE.jar`: 核心模块,提供了Spring框架的基础工具类和基本数据类型,...

    Spring IOC:找对象的一次革命(1)

    Spring IoC提供了BeanFactory和ApplicationContext两种容器类型,其中BeanFactory是基础的IoC容器,而ApplicationContext则提供了更多高级功能,如资源加载、事件发布等。 Spring IoC的配置主要通过XML或注解的方式...

    spring ioc以及事物架构图

    2. **创建BeanFactory实例**:接着,创建一个`DefaultListableBeanFactory`实例,它继承自`AbstractAutowireCapableBeanFactory`,是Spring IoC容器的核心实现之一。 ```java DefaultListableBeanFactory factory ...

    Spring注解驱动开发第41讲——Spring IOC容器创建源码解析(一)之BeanFactory的创建以及预准备工作(合起

    Spring注解驱动开发第41讲——Spring IOC容器创建源码解析(一)之BeanFactory的创建以及预准备工作(合起来整个过程)

    Spring源码分析_Spring_IOC

    在探讨Spring框架的核心组件之一——IOC(Inversion of Control,控制反转)容器之前,首先需要理解它在Spring框架中的角色与地位。对于Spring的使用者而言,IOC容器不仅是管理Bean(即应用中的对象实例)生命周期的...

    spring_ioc spring ioc

    ### Spring IoC容器的核心概念与应用 #### 一、IoC基本定义 IoC(Inversion of Control,控制反转)是一种设计思想,在Spring框架中主要体现在这样一种方式:原本在程序代码中由开发者自己控制的对象的创建过程以及...

Global site tag (gtag.js) - Google Analytics