日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

BeanDefinition 及其构造方式 BeanDefinitionBuilder, AbstractBeanDefinition

發布時間:2024/1/18 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 BeanDefinition 及其构造方式 BeanDefinitionBuilder, AbstractBeanDefinition 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

BeanDefinition 及其構造方式 BeanDefinitionBuilder, AbstractBeanDefinition

前言

  • 本文基于 jdk 8, spring-framework 5.2.x 編寫。
  • @author JellyfishMIX - github / blog.jellyfishmix.com
  • LICENSE GPL-2.0
  • BeanDefinition

    BeanDefinition 的屬性

    spring IoC 容器中的每一個 bean 都會有一個對應的 BeanDefinition 實例,該實例負責保存 bean 對象的所有必要信息,如下所示:

    屬性(property)說明
    classbean 全類名,必須是具體類,不能是抽象類或接口(因為抽象類或接口不能實例化)
    namebean 的名稱或 id
    scopebean 的作用域
    constructor argumentsbean 構造器參數(用于依賴注入)
    propertiesbean 屬性設置(用于依賴注入)
    autowiring modebean 自動綁定模式(例如通過名稱 byName)
    lazy initialization modebean 延遲初始化模式(延遲和非延遲)
    initialization methodbean 初始化回調方法名稱
    destruction methodbean 銷毀回調方法名稱

    需要說明的一點是:如果是自己直接通過 SingletonBeanRegistry#registerSingleton 向容器手動注入 Bean 的,不會存在這份 Bean 定義信息,這點需要注意。 Spring 內部有不少這樣的例子(因為這種Bean非常簡單,不需要定義信息):

    beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment()); bf.registerSingleton(WebApplicationContext.SERVLET_CONTEXT_BEAN_NAME, servletContext); Collections.unmodifiableMap(attributeMap));

    三種 BeanDefinition:

  • GenericBeanDefinition: 通用的 BeanDefinition,可以有 parentBeanDefinition。源碼的實現非常簡單,只增加了一個 parentName 的屬性值,其余的實現都在父類 AbstractBeanDefinition 里。
  • 通過 xml 方式配置 bean,最初被加載進來都是一個 GenericBeanDefinition,之后再逐漸解析的。
  • ChildBeanDefinition: 子 BeanDefinition,依賴于父類 RootBeanDefinition
  • 它可以繼承它父類的設置,即 ChildBeanDefinition 對 RootBeanDefinition 有一定的依賴關系。
  • 從 spring 2.5 開始,提供了一個更好的 GenericBeanDefinition,所以以后推薦使用它,不使用 ChildBeanDefinition。
  • RootBeanDefinition: 根 BeanDefinition,不能有 parentBeanDefinition
  • 在 配置文件中可以定義父和子,子用 ChildBeanDefiniton 表示,而沒有父的用 RootBeanDefinition 表示。
  • BeanDefinitionBuilder 中與三種 BeanDefinition 對應的構造方法

    /*** Programmatic means of constructing* {@link org.springframework.beans.factory.config.BeanDefinition BeanDefinitions}* using the builder pattern. Intended primarily for use when implementing Spring 2.0* {@link org.springframework.beans.factory.xml.NamespaceHandler NamespaceHandlers}.** @author Rod Johnson* @author Rob Harrop* @author Juergen Hoeller* @since 2.0*/ public final class BeanDefinitionBuilder {/*** Create a new {@code BeanDefinitionBuilder} used to construct a {@link GenericBeanDefinition}.** 創建一個通用的 beanDefinition,什么屬性都不填充*/public static BeanDefinitionBuilder genericBeanDefinition() {return new BeanDefinitionBuilder(new GenericBeanDefinition());}/*** Create a new {@code BeanDefinitionBuilder} used to construct a {@link GenericBeanDefinition}.** 創建一個通用的 beanDefinition,填充 bean 的 className** @param beanClassName the class name for the bean that the definition is being created for*/public static BeanDefinitionBuilder genericBeanDefinition(String beanClassName) {BeanDefinitionBuilder builder = new BeanDefinitionBuilder(new GenericBeanDefinition());builder.beanDefinition.setBeanClassName(beanClassName);return builder;}/*** Create a new {@code BeanDefinitionBuilder} used to construct a {@link GenericBeanDefinition}.** 創建一個通用的 beanDefinition,填充 bean 的 class** @param beanClass the {@code Class} of the bean that the definition is being created for*/public static BeanDefinitionBuilder genericBeanDefinition(Class<?> beanClass) {BeanDefinitionBuilder builder = new BeanDefinitionBuilder(new GenericBeanDefinition());builder.beanDefinition.setBeanClass(beanClass);return builder;}/*** Create a new {@code BeanDefinitionBuilder} used to construct a {@link GenericBeanDefinition}.** 創建一個通用的 beanDefinition,填充 bean 的 class,填充一個 bean 實例創建時會調用的回調函數** @param beanClass the {@code Class} of the bean that the definition is being created for* @param instanceSupplier a callback for creating an instance of the bean* @since 5.0*/public static <T> BeanDefinitionBuilder genericBeanDefinition(Class<T> beanClass, Supplier<T> instanceSupplier) {BeanDefinitionBuilder builder = new BeanDefinitionBuilder(new GenericBeanDefinition());builder.beanDefinition.setBeanClass(beanClass);builder.beanDefinition.setInstanceSupplier(instanceSupplier);return builder;}/*** Create a new {@code BeanDefinitionBuilder} used to construct a {@link RootBeanDefinition}.** 創建一個根 beanDefinition,填充 bean 的 className** @param beanClassName the class name for the bean that the definition is being created for*/public static BeanDefinitionBuilder rootBeanDefinition(String beanClassName) {return rootBeanDefinition(beanClassName, null);}/*** Create a new {@code BeanDefinitionBuilder} used to construct a {@link RootBeanDefinition}.** 創建一個根 beanDefinition,填充 bean 的 className,填充構造 bean 實例使用的方法名** @param beanClassName the class name for the bean that the definition is being created for* @param factoryMethodName the name of the method to use to construct the bean instance 構造 bean 實例使用的方法名*/public static BeanDefinitionBuilder rootBeanDefinition(String beanClassName, @Nullable String factoryMethodName) {BeanDefinitionBuilder builder = new BeanDefinitionBuilder(new RootBeanDefinition());builder.beanDefinition.setBeanClassName(beanClassName);builder.beanDefinition.setFactoryMethodName(factoryMethodName);return builder;}/*** Create a new {@code BeanDefinitionBuilder} used to construct a {@link RootBeanDefinition}.** 創建一個根 beanDefinition,填充 bean 的 class** @param beanClass the {@code Class} of the bean that the definition is being created for*/public static BeanDefinitionBuilder rootBeanDefinition(Class<?> beanClass) {return rootBeanDefinition(beanClass, null);}/*** Create a new {@code BeanDefinitionBuilder} used to construct a {@link RootBeanDefinition}.** 創建一個根 beanDefinition,填充 bean 的 class,填充構造 bean 實例使用的方法名** @param beanClass the {@code Class} of the bean that the definition is being created for* @param factoryMethodName the name of the method to use to construct the bean instance*/public static BeanDefinitionBuilder rootBeanDefinition(Class<?> beanClass, @Nullable String factoryMethodName) {BeanDefinitionBuilder builder = new BeanDefinitionBuilder(new RootBeanDefinition());builder.beanDefinition.setBeanClass(beanClass);builder.beanDefinition.setFactoryMethodName(factoryMethodName);return builder;}/*** Create a new {@code BeanDefinitionBuilder} used to construct a {@link ChildBeanDefinition}.** 創建一個子 beanDefinition,填充父 beanDefinition 的名字** @param parentName the name of the parent bean*/public static BeanDefinitionBuilder childBeanDefinition(String parentName) {return new BeanDefinitionBuilder(new ChildBeanDefinition(parentName));}/*** The {@code BeanDefinition} instance we are creating.** 創建出的 beanDefinition 實例*/private final AbstractBeanDefinition beanDefinition;

    AbstractBeanDefinition

    BeanDefinition 是個接口,AbstractBeanDefinition 是這個接口的實現類,很多常見的 bean 屬性在 AbstractBeanDefinition 中。這是經典的工廠模式,抽象出接口去規范工廠生產的實體類的行為。

    另外 GenericBeanDefinition 只是子類實現,大部分的屬性在 AbstractBeanDefinition 中。

    public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessorimplements BeanDefinition, Cloneable {/*** bean 對應的 class(用一個 Class 對象來表示)*/@Nullableprivate volatile Object beanClass;/*** bean 的作用范圍* 對應 bean 屬性 scope*/@Nullableprivate String scope = SCOPE_DEFAULT;/*** 是否是抽象類* 對應 bean 屬性 abstract*/private boolean abstractFlag = false;/*** 是否延遲加載* 對應 bean 屬性 lazy-init*/@Nullableprivate Boolean lazyInit;/*** 自動裝配模式,自動注入模式* 對應 bean 屬性 autowire*/private int autowireMode = AUTOWIRE_NO;/*** 依賴檢查模式*/private int dependencyCheck = DEPENDENCY_CHECK_NONE;/*** 用來表示一個 bean 的實例化依靠另一個 bean 先實例化* 這里只會存放<bean/>標簽的depends-on屬性或是@DependsOn注解的值*/@Nullableprivate String[] dependsOn;/*** autowire-candidate 屬性設置為 false,這樣容器在查找自動裝配對象時,* 將不考慮該 bean,即它不會被考慮作為其他 bean 自動裝配的候選者,* 但是該 bean 本身還是可以使用自動裝配來注入其他 bean 的*/private boolean autowireCandidate = true;/*** 當某個 bean 的某個屬性自動裝配有多個候選者(候選者包括此 bean)時,是否優先注入,即 @Primary 注解* 對應 bean 屬性 primary*/private boolean primary = false;/*** 用于記錄 qualifier* AutowireCandidateQualifier 用于解析自動裝配的候選者*/private final Map<String, AutowireCandidateQualifier> qualifiers = new LinkedHashMap<>();/*** 用于初始化 bean 的回調函數,一旦指定,這個方法會覆蓋工廠方法以及構造函數中的元數據* 可以理解為,通過這個函數的邏輯初始化 bean,而不是構造函數或是工廠方法*/@Nullableprivate Supplier<?> instanceSupplier;/*** 是否允許訪問非 public 方法和屬性,應用場景是構造函數, 工廠方法, init, destroy 方法解析構造函數*/private boolean nonPublicAccessAllowed = true;/*** 指定解析構造函數的模式,是寬松還是嚴格* 如果為false,則在以下情況* interface ITest{}* class ITestImpl implements ITest{};* class Main {* Main(ITest i) {}* Main(ITestImpl i) {}* }* 拋出異常,因為Spring無法準確定位哪個構造函數程序設置*/private boolean lenientConstructorResolution = true;/*** bean 的 factoryBeanName* <bean id = "currentTime" factory-bean = "instanceFactoryBean" factory-method = "createTime" />*/@Nullableprivate String factoryBeanName;/*** bean 的 factoryMethodName* <bean id = "currentTime" factory-bean = "instanceFactoryBean" factory-method = "createTime" />*/@Nullableprivate String factoryMethodName;/*** 記錄構造函數注入屬性,對應 bean 屬性 constructor-arg*/@Nullableprivate ConstructorArgumentValues constructorArgumentValues;/*** 普通屬性集合*/@Nullableprivate MutablePropertyValues propertyValues;/*** 方法重寫的持有者,記錄 lookup-method, replaced-method 元素*/private MethodOverrides methodOverrides = new MethodOverrides();/*** 初始化方法*/@Nullableprivate String initMethodName;/*** 銷毀方法*/@Nullableprivate String destroyMethodName;/*** 是否執行 init-method*/private boolean enforceInitMethod = true;/*** 是否執行 destroy-method*/private boolean enforceDestroyMethod = true;/*** 是否是合成類。根據用戶自定義的類生成的 bean 不是合成類,應用程序(框架)生成的是合成類(例如生成 aop 代理類時,不是用戶自定義的,這個就是合成類)*/private boolean synthetic = false;/*** 這個 bean 的角色,ROLE_APPLICATION:用戶,ROLE_INFRASTRUCTURE:完全內部使用,與用戶無關,* ROLE_SUPPORT:某些龐大配置的一部分*/private int role = BeanDefinition.ROLE_APPLICATION;/*** bean 的描述*/@Nullableprivate String description;/*** 這個 bean 定義的資源*/@Nullableprivate Resource resource; }

    AbstractBeanDefinition 定義了一系列描述 bean 的屬性,可以看到 bean 屬性的某些默認值(例如默認為單例)。這個類的屬性部分可以在 xml 配置文件中找到相應的屬性或是標簽(例如 AbstractBeanDefinition 的 scope 屬性對應 xml 配置文件中的 scope 屬性)。

    BeanDefinition 的構造方式

  • 通過 BeanDefinitionBuilder
  • 通過 AbstractBeanDefinition 及其派生類
  • public static void main(String[] args) {// 1. 通過 BeanDefinitionBuilder 構建BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User.class);// 設置 bean 屬性,builder 模式可以做到鏈式調用beanDefinitionBuilder.addPropertyValue("id", 1).addPropertyValue("name", "小明");// 獲取 BeanDefinition 實例BeanDefinition abstractBeanDefinition = beanDefinitionBuilder.getBeanDefinition();// BeanDefinition 不是 Bean 的終態,可以自定義修改// 2. 通過 AbstractBeanDefinition 及其派生類構建AbstractBeanDefinition genericBeanDefinition = new GenericBeanDefinition();// 設置 bean 類型genericBeanDefinition.setBeanClass(User.class);// 通過 MutablePropertyValues 批量操作屬性,這也是一種鏈式調用MutablePropertyValues propertyValues = new MutablePropertyValues();// propertyValues.add("id", 1);// propertyValues.add("name", "小明");propertyValues.add("id", 1).add("name", "小明");genericBeanDefinition.setPropertyValues(propertyValues);}

    BeanDefinition 什么時候會用到?

    spirng 的 ioc 容器實例化 bean 的過程需要 BeanDefinition 中的信息,它是實例化 Bean 的原材料。

    例如 org.springframework.context.config.AbstractPropertyLoadingBeanDefinitionParser,這是一個 BeanDefinitionParser (接口)的實現類,用來解析 xml 中的 context:property-… 這樣的元素。

    解析 xml 時使用 BeanDefinition

    package org.springframework.beans.factory.xml;/*** Abstract parser for &lt;context:property-.../&gt; elements.* *** @author Juergen Hoeller* @author Arjen Poutsma* @author Dave Syer* @since 2.5.2*/ abstract class AbstractPropertyLoadingBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { @Overrideprotected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {String location = element.getAttribute("location");if (StringUtils.hasLength(location)) {location = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(location);String[] locations = StringUtils.commaDelimitedListToStringArray(location);builder.addPropertyValue("locations", locations);}String propertiesRef = element.getAttribute("properties-ref");if (StringUtils.hasLength(propertiesRef)) {builder.addPropertyReference("properties", propertiesRef);}String fileEncoding = element.getAttribute("file-encoding");if (StringUtils.hasLength(fileEncoding)) {builder.addPropertyValue("fileEncoding", fileEncoding);}String order = element.getAttribute("order");if (StringUtils.hasLength(order)) {builder.addPropertyValue("order", Integer.valueOf(order));}builder.addPropertyValue("ignoreResourceNotFound",Boolean.valueOf(element.getAttribute("ignore-resource-not-found")));builder.addPropertyValue("localOverride",Boolean.valueOf(element.getAttribute("local-override")));builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);}}

    具體的邏輯我們可以先不管,能看到 builder.addPropertyValue 這樣的代碼,這里的 doParse 方法一邊在解析 xml,一邊在使用 BeanDefinitionBuilder 構建 BeanDefinition。

    通過 BeanDefinition 實例化 bean

    在一個 AbstractBeanFactory 的子類中,可以看到有一個方法 doCreateBean 在根據 BeanDefinition 實例化 bean。

    package org.springframework.beans.factory.support;public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactoryimplements AutowireCapableBeanFactory {/*** Actually create the specified bean. Pre-creation processing has already happened* at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.* <p>Differentiates between default bean instantiation, use of a* factory method, and autowiring a constructor.* @param beanName the name of the bean* @param mbd the merged bean definition for the bean* @param args explicit arguments to use for constructor or factory method invocation* @return a new instance of the bean* @throws BeanCreationException if the bean could not be created* @see #instantiateBean* @see #instantiateUsingFactoryMethod* @see #autowireConstructor*/protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)

    bean 構建的具體邏輯我們以后再分析。這里只是舉例一下 BeanDefinition 用到的地方,對 BeanDefinition 從構建到使用有一個直觀的印象。

    總結

    以上是生活随笔為你收集整理的BeanDefinition 及其构造方式 BeanDefinitionBuilder, AbstractBeanDefinition的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。