本文所使用源码包版本:spring-beans-5.0.7.RELEASE.
1. 如何注册?
推荐通过实现 BeanDefinitionRegistryPostProcessor 接口操作 BeanDefinitionRegistry
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {/*** Modify the application context's internal bean definition registry after its* standard initialization. All regular bean definitions will have been loaded,* but no beans will have been instantiated yet. This allows for adding further* bean definitions before the next post-processing phase kicks in.* @param registry the bean definition registry used by the application context* @throws org.springframework.beans.BeansException in case of errors*/void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;}
2. 测试代码
我们有个类 Person,把它手动添加到Spring 容器中成为一个bean:
public class Person {private String name ;public void test(){System.out.println("hello world!");}public void setName(String name) {this.name = name;}}
@EnableAspectJAutoProxy@ComponentScan("com.jimbean.spring.test")public class BootStrap {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext= new AnnotationConfigApplicationContext(BootStrap.class);DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getBeanFactory();// 这里也可以使用 BeanDefinitionBuilderGenericBeanDefinition beanDefinition = new GenericBeanDefinition();beanDefinition.setBeanClass(Person.class);beanFactory.registerBeanDefinition("person", beanDefinition);Person person = (Person) applicationContext.getBean("person");person.test();}}
程序运行结果:
hello world!
person的bean,并且调用方案打印了调用结果。
public class Person {private String name ;@AutowiredAnimal animal;public void test(){y.test();System.out.println("hello world!");}public void setName(String name) {this.name = name;}}
@Componentpublic class Animal {public Animal() {System.out.println("Construct Animal");}public void test(){System.out.println("Animal.test()...");}}
上述测试代码输出结果:
Construct Animal
Animal.test()...
hello world!
3. 源码解读:
BeanDefinition 接口:

/*** Register a new bean definition with this registry.* Must support RootBeanDefinition and ChildBeanDefinition.* @param beanName the name of the bean instance to register* @param beanDefinition definition of the bean instance to register* @throws BeanDefinitionStoreException if the BeanDefinition is invalid* or if there is already a BeanDefinition for the specified bean name* (and we are not allowed to override it)* @see RootBeanDefinition* @see ChildBeanDefinition*/void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)throws BeanDefinitionStoreException;
@Overridepublic void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)throws BeanDefinitionStoreException {Assert.hasText(beanName, "Bean name must not be empty");Assert.notNull(beanDefinition, "BeanDefinition must not be null");if (beanDefinition instanceof AbstractBeanDefinition) {try {//校验传入beanDefinition的正确性((AbstractBeanDefinition) beanDefinition).validate();}catch (BeanDefinitionValidationException ex) {throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,"Validation of bean definition failed", ex);}}BeanDefinition oldBeanDefinition;oldBeanDefinition = this.beanDefinitionMap.get(beanName);if (oldBeanDefinition != null) {//如果已存在该bean名称的beanDefinition,并且不允许覆盖,则抛异常if (!isAllowBeanDefinitionOverriding()) {throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +"': There is already [" + oldBeanDefinition + "] bound.");}else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTUREif (this.logger.isWarnEnabled()) {this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +"' with a framework-generated bean definition: replacing [" +oldBeanDefinition + "] with [" + beanDefinition + "]");}}else if (!beanDefinition.equals(oldBeanDefinition)) {if (this.logger.isInfoEnabled()) {this.logger.info("Overriding bean definition for bean '" + beanName +"' with a different definition: replacing [" + oldBeanDefinition +"] with [" + beanDefinition + "]");}}else {if (this.logger.isDebugEnabled()) {this.logger.debug("Overriding bean definition for bean '" + beanName +"' with an equivalent definition: replacing [" + oldBeanDefinition +"] with [" + beanDefinition + "]");}}this.beanDefinitionMap.put(beanName, beanDefinition);}else {//检查beanFactory的bean创建阶段是否已开始,可以理解为容器是否已经初始化过了if (hasBeanCreationStarted()) {// Cannot modify startup-time collection elements anymore (for stable iteration)synchronized (this.beanDefinitionMap) {//把新加入的beanName-beanDefinition映射加入beanDefinitionMap//把beanName加入的维护的beanDefinitionName列表(ArrayList)中this.beanDefinitionMap.put(beanName, beanDefinition);List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);updatedDefinitions.addAll(this.beanDefinitionNames);updatedDefinitions.add(beanName);this.beanDefinitionNames = updatedDefinitions;//如果手动注册的单例bean名称包含了beanName,需要移除//这个地方默认构造的beanDefinition对象作用域也是“”,等价于单例,但是却没有把 beanName加入到manualSingletonNames集合(LinkedHashSet)中//最终beanName对应的bean实例化后,manualSingletonNames还是没有这个beanName,略奇怪。。。if (this.manualSingletonNames.contains(beanName)) {Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);updatedSingletons.remove(beanName);this.manualSingletonNames = updatedSingletons;}}}else {// Still in startup registration phasethis.beanDefinitionMap.put(beanName, beanDefinition);this.beanDefinitionNames.add(beanName);this.manualSingletonNames.remove(beanName);}this.frozenBeanDefinitionNames = null;}//如果oldBeanDefinition不为null,且单例池缓存中已经有beanName对应的bean,则重置给定bean的所有bean定义缓存,包括从其派生的bean的缓存。if (oldBeanDefinition != null || containsSingleton(beanName)) {resetBeanDefinition(beanName);}}
SingletonBeanRegistry 接口:
SingletonBeanRegister接口,是单例bean的管理接口,也可以用来注册单例bean,方法:
void registerSingleton(String beanName, Object singletonObject);
@EnableAspectJAutoProxy@ComponentScan("com.jimbean.spring.test")public class BootStrap {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext= new AnnotationConfigApplicationContext(BootStrap.class);DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getBeanFactory();beanFactory.registerSingleton("person", new Person());Person person = (Person) applicationContext.getBean("person");person.test();}}
代码也很简单,但是需要注意的是:
1. bean依赖项不好处理
2. 待注入的实例应该被完全初始化,注册表不会执行任何初始化回调方法,比如InitializingBean的{@code afterPropertiesSet}方法
文章转载自编程阁楼,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




