日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

Spring BeanDefinition元信息定義方式

Bean Definition是一個包含Bean元數據的對象。它描述了如何創建Bean實例、Bean屬性的值以及Bean之間的依賴關系。可以使用多種方式來定義 Bean Definition 元信息,包括:

  1. XML 配置文件:使用<bean>標簽定義 Bean 元數據,可以指定 Bean 類型、屬性值和依賴項等信息。
  2. 注解:使用@Component、@Service、@Repository 等注解標記 Bean 類,并使用 @Autowired注解注入依賴項。
  3. JAVA 配置類:使用@Configuration 和 @Bean注解定義Bean元數據,可以指定 Bean 類型、屬性值和依賴項等信息。

除此之外,還可以通過實現
BeanDefinitionRegistryPostProcessor 接口來自定義 Bean Definition 的生成過程。這個接口有一個方法 postProcessBeanDefinitionRegistry(),允許開發人員動態地添加、修改或刪除Bean Definition元信息。

XML配置文件定義Bean的元數據

<bean id="user" class="org.thinging.in.spring.ioc.overview.domAIn.User">
  <property name="id" value="1"/>
  <property name="name" value="Liutx"/>
</bean>

 

注解定義Bean的元數據

@Service(value = "HelloService")
public class HelloService {

    private final Logger logger = LoggerFactory.getLogger(HelloService.class);

    private final HelloAsyncService helloAsyncService;

        public HelloService(HelloAsyncService helloAsyncService) {
        this.helloAsyncService = helloAsyncService;
    }
}

 

value = "HelloService" 即為Bean:HelloService的元數據,在構造方法中的依賴關系同樣屬于元數據。

Java 配置類定義Bean的元數據

@Component(value = "balanceredisProcessor")
public class BalanceRedisProcessorService implements EntryHandler<Balance>, Runnable {

    @Autowired(required = true)
    public BalanceRedisProcessorService(RedisUtils redisUtils,
                                        CanalConfig canalConfig,
                                        @Qualifier("ownThreadPoolExecutor") Executor executor, RocketMQProducer rocketMqProducer) {
        this.redisUtils = redisUtils;
        this.canalConfig = canalConfig;
        this.executor = executor;
        this.rocketMQProducer = rocketMqProducer;
    }
}

 

@Component(value = "balanceRedisProcessor") 是
Bean:BalanceRedisProcessorService的元數據,在構造方法中的依賴關系同樣屬于元數據。

BeanDefinition的元數據解析

在Spring中,無論是通過XML、注解、Java配置類定義Bean元數據,最終都是需要轉換成BeanDefinition對象,然后被注冊到Spring容器中。

而BeanDefinition的創建過程,確實是通過AbstractBeanDefinition及其派生類、``等一系列工具類實現的。

  • 當我們使用XML配置時,Spring會解析XML文件,將其中的Bean元數據信息轉換成對應的BeanDefinition對象,然后注冊到Spring容器中。在這個過程中,Spring內部會使用XmlBeanDefinitionReader等相關工具類,將XML文件中定義的Bean元數據轉換成BeanDefinition對象。
  • 當我們使用注解方式或Java配置類方式定義Bean元數據時,Spring會掃描相應的注解或Java配置類,然后根據其定義生成對應的BeanDefinition對象,并注冊到Spring容器中。在這個過程中,Spring內部會使用AnnotationConfigApplicationContext等相關工具類,將注解或Java配置類中定義的Bean元數據轉換成BeanDefinition對象。

源碼分析XML是如何轉化為Spring BeanDefinition的

將xml文件中的配置轉為為BeanDefinition需要依賴自XmlBeanDefinitionReader類中的loadBeanDefinitions方法。

選自:Spring Framework 5.2.20 RELEASE版本的XmlBeanDefinitionReader。

private final ThreadLocal<Set<EncodedResource>> resourcesCurrentlyBeingLoaded =
        new NamedThreadLocal<Set<EncodedResource>>("XML bean definition resources currently being loaded"){
            @Override
            protected Set<EncodedResource> initialValue() {
                return new HashSet<>(4);
            }
        };

/**
 * Load bean definitions from the specified XML file.
 * @param encodedResource the resource descriptor for the XML file,
 * allowing to specify an encoding to use for parsing the file
 * @return the number of bean definitions found
 * @throws BeanDefinitionStoreException in case of loading or parsing errors
 */
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
    Assert.notNull(encodedResource, "EncodedResource must not be null");
    if (logger.isTraceEnabled()) {
        logger.trace("Loading XML bean definitions from " + encodedResource);
    }

    Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();

    if (!currentResources.add(encodedResource)) {
        throw new BeanDefinitionStoreException(
                "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
    }

    try (InputStream inputStream = encodedResource.getResource().getInputStream()) {
        InputSource inputSource = new InputSource(inputStream);
        if (encodedResource.getEncoding() != null) {
            inputSource.setEncoding(encodedResource.getEncoding());
        }
        // 實際上從指定的 XML 文件加載 Bean 定義
        return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
    }
    catch (IOException ex) {
        throw new BeanDefinitionStoreException(
                "IOException parsing XML document from " + encodedResource.getResource(), ex);
    }
    finally {
        currentResources.remove(encodedResource);
        if (currentResources.isEmpty()) {
            this.resourcesCurrentlyBeingLoaded.remove();
        }
    }
}


//實際上從指定的 XML 文件加載 Bean 定義
/**
 * Actually load bean definitions from the specified XML file.
 * @param inputSource the SAX InputSource to read from
 * @param resource the resource descriptor for the XML file
 * @return the number of bean definitions found
 * @throws BeanDefinitionStoreException in case of loading or parsing errors
 * @see #doLoadDocument
 * @see #registerBeanDefinitions
 */
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
        throws BeanDefinitionStoreException {

    try {
        Document doc = doLoadDocument(inputSource, resource);
        int count = registerBeanDefinitions(doc, resource);
        if (logger.isDebugEnabled()) {
            logger.debug("Loaded " + count + " bean definitions from " + resource);
        }
        return count;
    }
}

 

  1. 使用ThreadLocal線程級別的變量存儲帶有編碼資源的集合,保證每個線程都可以訪問到XmlBeanDefinitionReader在加載XML配置文件時當前正在加載的資源,以確保加載過程中的完整性和正確性。
  2. 在ThreadLocal中獲取到當前正在加載的xml資源,轉換為輸入流
  3. 開始執行doLoadBeanDefinitions,實際上從指定的 XML 文件加載 Bean 定義,該方法會返回加載的Bean定義數量。
  4. doLoadBeanDefinitions方法中,首先調用doLoadDocument方法加載XML文件并生成一個Document對象。
  5. 然后,調用registerBeanDefinitions方法來注冊Bean定義,將其放入Spring容器中。該方法會返回注冊的Bean定義數量。
  6. 最后,根據需要記錄日志信息,并返回加載的Bean定義數量。

源碼分析配置類、注解是如何轉化為Spring BeanDefinition的

在Spring中,配置類和注解都可以被轉換為Bean定義(BeanDefinition)。下面是關于如何將配置類和注解轉換為Bean定義的簡要源碼分析:

  1. 配置類轉換為Bean定義:
  • 當使用Java配置類時,Spring會通過解析配置類中的注解來生成相應的Bean定義。主要實現是通過ConfigurationClassParser類完成的。 ConfigurationClassParser會解析配置類上的注解,包括@Configuration、@ComponentScan、@Bean等,然后將其轉換為對應的Bean定義。 在解析過程中,Spring會創建一個ConfigurationClass對象表示配置類,并根據不同的注解類型生成相應的Bean定義,包括RootBeanDefinition和MethodMetadata。 RootBeanDefinition代表配置類本身,而MethodMetadata代表配置類中的方法上的注解,例如@Bean注解。 最終,這些生成的Bean定義會被注冊到DefaultListableBeanFactory中,以供后續的Bean實例化和依賴注入。
  1. 注解轉換為Bean定義:
  • 當使用注解方式配置Bean時,Spring會掃描指定的包或類,并解析其中的注解來生成Bean定義。 Spring提供了AnnotationBeanDefinitionReader類用于處理注解,它會掃描指定的包路徑或類,并根據注解生成相應的Bean定義。 在掃描過程中,AnnotationBeanDefinitionReader會解析常見的注解,比如@Component、@Controller、@Service、@Repository等,然后生成相應的Bean定義。 注解生成的Bean定義同樣會被注冊到DefaultListableBeanFactory中,以供后續的Bean實例化和依賴注入。

總而言之,無論是配置類還是注解,Spring都會通過解析注解并生成對應的Bean定義,最終將這些Bean定義注冊到
DefaultListableBeanFactory中。這樣,在容器啟動時,Spring就能夠根據這些Bean定義來實例化Bean并進行依賴注入。

配置類、注解轉換為Spring BeanDefition源碼后續博客中展示,敬請期待。

如何手動構造BeanDefinition

Bean定義

public class User {

    private Long id;

    private String name;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + ''' +
                '}';
    }
}

 

通過BeanDefinitionBuilder構建

//通過BeanDefinitionBuilder構建
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User.class);
//通過屬性設置
beanDefinitionBuilder.addPropertyValue("id", 1L)
        .addPropertyValue("name","公眾號:種棵代碼技術樹");

//獲取BeanDefinition實例
BeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
// BeanDefinition 并非 Bean 終態,可以自定義修改
System.out.println(beanDefinition);

 

通過AbstractBeanDefinition以及派生類

// 2. 通過 AbstractBeanDefinition 以及派生類
GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition();
//設置Bean類型
genericBeanDefinition.setBeanClass(User.class);
//通過 MutablePropertyValues 批量操作屬性
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("id",1L)
        .add("name","公眾號:種棵代碼技術樹");
// 通過 set MutablePropertyValues 批量操作屬性
genericBeanDefinition.setPropertyValues(propertyValues);

 

作者:FirstMrRight
鏈接:
https://juejin.cn/post/7320779681673134091

分享到:
標簽:Spring
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定