注册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;
}
}
}