spring-core-4-35 | 注册Spring Bean:如何将BeanDefinition注册到IoC容器?

本文深入探讨Spring框架中Bean注册的不同方式,包括XML配置、Java注解(@Bean、@Component、@Import)、Java API(BeanDefinitionRegistry、SingletonBeanRegistry)等,并通过具体代码示例进行演示。
摘要由CSDN通过智能技术生成

注册Spring Bean

BeanDefinition 注册

XML 配置元信息

• <bean name=”…” … />
还有properties文件的方式, 后面予以介绍
因为XML的方式之前 讲了太多, 这里就不展开了

Java 注解配置元信息

• @Bean

• @Component

• @Import

Java API 配置元信息

也是最底层的方式

• 命名方式:BeanDefinitionRegistry#registerBeanDefinition(String,BeanDefinition)

• 非命名方式:

BeanDefinitionReaderUtils#registerWithGeneratedName(AbstractBeanDefinition,Be

anDefinitionRegistry)

• 配置类方式:AnnotatedBeanDefinitionReader#register(Class…)

外部单例对象注册

Java API 配置元信息

• SingletonBeanRegistry#registerSingleton

代码示例

这里只介绍怎么使用, 后面在介绍原理
spring-core项目
搜索 35 | 注册Spring Bean
AnnotationBeanDefinitionDemo.java

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.geekbang.thinking.in.spring.bean.definition;

import org.geekbang.thinking.in.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import static org.springframework.beans.factory.support.BeanDefinitionBuilder.genericBeanDefinition;

/**
 * 35 | 注册Spring Bean:如何将BeanDefinition注册到IoC容器?
 * <p>
 * 注解 BeanDefinition 示例
 * 1. 通过 @Bean 方式定义
 * 2. 通过 @Component 方式
 * 3. 通过 @Import 来进行导入
 * @Component和@Import有一个重复导入的情况
 * 上面这三种方式如果导入的是同一个对象, id就会一致, 是不会出现重复的, 这是spring很严谨的地方
 * 4. 通过 BeanDefinition 注册 API 实现
 * 1.命名 Bean 的注册方式
 * 2. 非命名 Bean 的注册方法
 * 两种方式如果bean的id不同, 也就会有两个不同的对象会注册
 * <p>
 * • BeanDefinition 注册
 *      • XML 配置元信息
 *          • <bean name=”...” ... />
 *      • Java 注解配置元信息
 *          • @Bean
 *          • @Component
 *          • @Import
 *      • Java API 配置元信息
 *          • 命名方式:BeanDefinitionRegistry#registerBeanDefinition(String,BeanDefinition)
 *          • 非命名方式:
 *          BeanDefinitionReaderUtils#registerWithGeneratedName(AbstractBeanDefinition,BeanDefinitionRegistry)
 *          • 配置类方式:AnnotatedBeanDefinitionReader#register(Class...)
 * • 外部单例对象注册
 *      • Java API 配置元信息
 *          • SingletonBeanRegistry#registerSingleton   见 SingletonBeanRegistrationDemo.java
 *
 * @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
 * @since
 */
// 3. 通过 @Import 来进行导入
@Import(AnnotationBeanDefinitionDemo.Config.class)
public class AnnotationBeanDefinitionDemo {

    public static void main(String[] args) {
        // 创建 BeanFactory 容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        // 这里Config类后来换成注解@Import来进行导入
        //applicationContext.register(Config.class);
        // 注册 Configuration Class(配置类)
        applicationContext.register(AnnotationBeanDefinitionDemo.class);

        // 4. 通过 BeanDefinition 注册 API 实现
        // 4.1. 命名 Bean 的注册方式
        registerUserBeanDefinition(applicationContext, "mercyblitz-user");
        // 4.2. 非命名 Bean 的注册方法
        registerUserBeanDefinition(applicationContext);

        // 启动 Spring 应用上下文
        applicationContext.refresh();
        // 按照类型依赖查找
        // 这里不会打印别名, 因为别名不是一个单独的bean
        System.out.println("Config 类型的所有 Beans" + applicationContext.getBeansOfType(Config.class));
        System.out.println("User 类型的所有 Beans" + applicationContext.getBeansOfType(User.class));
        // 显示地关闭 Spring 应用上下文
        applicationContext.close();
    }

    public static void registerUserBeanDefinition(BeanDefinitionRegistry registry, String beanName) {
        BeanDefinitionBuilder beanDefinitionBuilder = genericBeanDefinition(User.class);
        beanDefinitionBuilder
                .addPropertyValue("id", 1L)
                .addPropertyValue("name", "小马哥");

        // 判断如果 beanName 参数存在时
        if (StringUtils.hasText(beanName)) {
            // 注册 BeanDefinition
            registry.registerBeanDefinition(beanName, beanDefinitionBuilder.getBeanDefinition());
        } else {
            // 非命名 Bean 注册方法
            BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinitionBuilder.getBeanDefinition(), registry);
        }
    }

    public static void registerUserBeanDefinition(BeanDefinitionRegistry registry) {
        registerUserBeanDefinition(registry, null);
    }

    // 2. 通过 @Component 方式
    @Component // 定义当前类作为 Spring Bean(组件)
    public static class Config {

        // 1. 通过 @Bean 方式定义

        /**
         * 通过 Java 注解的方式,定义了一个 Bean
         * name有多个时, 第一个是bean的name, 后面的都是alias别名
         */
        @Bean(name = {"user", "xiaomage-user"})
        public User user() {
            User user = new User();
            user.setId(1L);
            user.setName("小马哥");
            return user;
        }
    }


}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值