二、注册的具体过程
1、职责类
- 由DefaultListableBeanFactory来完成,该接口实现了ListableBeanFactory和BeanDefinitionRegistry接口;
2、源码解读
前一节中谈到,生成BeanDefinition后,由
BeanDefinitionReaderUtils.registerBeanDefinition()来完成向容器中注册Bean定义信息,该方法即
调用了下面的registerBeanDefinition()方法;下面是DefaultListableBeanFactory实现
BeanDefinitionRegistry接口的部分:
//---------------------------------------------------------------------
// Implementation of BeanDefinitionRegistry interface
//---------------------------------------------------------------------
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "'beanName' must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
// 普通的bean,在生成BeanDefinition时,都是GenericBeanDefinition的实例,它是AbstractBeanDefinition的子类
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
// 开始注册到容器,注意了
synchronized (this.beanDefinitionMap) {
// 先看一下存放BeanDefinition的map里是否已经包含了相同beanName的BeanDefinition
Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
// 如果已经存在,则需要根据容器的属性(beanDefinition是否可以被覆盖,默认为true)来做不同的处理
if (!this.allowBeanDefinitionOverriding) {
// 如果不允许覆盖,抛错
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + oldBeanDefinition + "] bound.");
}
else {
// 允许覆盖,继续后面的操作
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName +
"': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
}
else {
// 如果map中没有该beanName,则将beanNames存放在list中
this.beanDefinitionNames.add(beanName);
this.frozenBeanDefinitionNames = null;
}
// 将beanName及beanDefinition放在map中,完成注册
this.beanDefinitionMap.put(beanName, beanDefinition);
resetBeanDefinition(beanName);
}
}
public void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
Assert.hasText(beanName, "'beanName' must not be empty");
synchronized (this.beanDefinitionMap) {
// 从map中清除指定beanName的beanDefinition
BeanDefinition bd = (BeanDefinition) this.beanDefinitionMap.remove(beanName);
if (bd == null) {
if (this.logger.isTraceEnabled()) {
this.logger.trace("No bean named '" + beanName + "' found in " + this);
}
throw new NoSuchBeanDefinitionException(beanName);
}
this.beanDefinitionNames.remove(beanName);
this.frozenBeanDefinitionNames = null;
resetBeanDefinition(beanName);
}
}
3、小结
- 到现在为止,只是将XML里定义的bean定义信息生成GenericBeanDefinition实例,然后注册到容器中(所谓注册,也就是存放在一个map中,key为beanName,value为BeanDefinition实例);
- 其实,后面还有很多工作要做。。。。。。
分享到:
相关推荐
2. `pk-ek-provider`:服务提供者模块,实现了具体的业务逻辑,并通过Spring Cloud的`@EnableEurekaClient`注解向Eureka服务器注册自身。 3. `pk-ek-invoker`:服务消费者模块,通过Ribbon从Eureka获取服务提供者的...
Spring Data Commons是Spring框架的一个重要组成部分,它为Spring Data项目提供了一套通用的基础设施,简化了与各种数据存储进行交互的过程。这个1.13.0.RELEASE版本是该模块的一个稳定版本,包含了对多种数据访问...
4. **配置中心**:Spring Cloud Config Server是集中管理应用配置的工具,它允许我们在不重启服务的情况下动态更新配置。项目中可能有一个名为`config-server`的模块,提供配置文件的管理和推送功能。 在实际开发中...
4. **MapperScannerConfigurer**:这个配置类可以自动扫描指定包下的Mapper接口,并将其注册到Spring容器中,免去了手动配置的繁琐步骤。 在具体使用时,我们需要在Spring的配置文件中添加MyBatis-Spring的相关配置...
MyBatis-Spring是MyBatis和Spring框架的集成库,旨在简化在Spring应用中使用MyBatis的过程,实现两者的无缝连接。本篇文章将深入探讨MyBatis-Spring的核心功能,以及1.0.2版本的具体特性。 首先,我们要理解MyBatis...
SpringCloud是基于SpringBoot进行微服务架构的一系列工具集合,它为开发者提供了在分布式系统(如配置管理、服务发现、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话、集群状态)...
Spring Boot是由Pivotal团队提供的全新框架,其设计目标是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式(如约定优于配置)来消除大部分的配置,从而使开发者可以更快速地构建项目。Spring ...
1. 用户注册与登录:通过Spring Security LDAP,可以实现用户注册时的信息存储到LDAP目录,以及用户登录时的身份验证。 2. 权限分配:根据LDAP中的用户组信息,动态地分配用户的权限,实现细粒度的访问控制。 3. ...
4. **实现服务接口**:为服务接口创建实现类,提供具体的服务逻辑。 5. **暴露服务**:使用`@Service`注解标记服务实现类,这个注解告诉Dubbo该类是服务提供者的一部分。 6. **消费服务**:在服务消费者端,使用`@...
4. 配置MapperScannerConfigurer:Spring扫描带有特定注解的Mapper接口,并将它们注册到Spring容器中。 5. 使用@Autowired注入Mapper:在需要使用Mapper的地方,通过@Autowired注解自动注入对应的Mapper接口。 资源...
本文将深入探讨Spring Boot如何与MyBatis集成,并以`spring-boot-starter-mybatis-spring-boot-2.1.4`为例,解析集成过程及其实现原理。 一、Spring Boot与MyBatis的集成原理 Spring Boot通过`spring-boot-starter...
本篇文章将深入探讨如何将SpringCloud与Nacos进行有效整合,通过具体的项目实例——"springcloud-nacos-demo",来解析这一过程的关键知识点。 一、SpringCloud简介 SpringCloud是基于Spring Boot实现的云应用开发...
4. **应用配置**:在Spring Boot应用中,我们通常通过`application.yml`或`application.properties`文件配置服务注册的相关参数,例如`spring.cloud.nacos.discovery.server-addr`来指定Nacos服务器地址。...
在Spring配置文件中启用AOP并注册切面类,或者在Java配置类中使用`@EnableAspectJAutoProxy`注解。 6. 应用场景 - 日志记录:在方法调用前后记录日志,无需在每个业务方法中重复代码。 - 事务管理:使用`@...
1. 服务生产者:实现具体业务逻辑,对外提供API接口,通过Eureka注册自身服务,以便被其他服务发现和调用。 2. 服务消费者:查找并调用服务生产者提供的API,实现业务流程。服务消费者同样需要在Eureka中注册,以便...
1. **自动配置(Auto Configuration)**:这是Spring Boot的核心特性之一,gRPC-Spring-Boot-Starter通过`@EnableAutoConfiguration`注解来触发自动配置过程。它会根据项目中引入的依赖,自动创建并注册相关的bean,...
- **示例项目**:SpringSource 社区提供了示例项目 sparklr2 和 tonr2,分别作为资源服务器和服务端,通过 Maven 构建并部署在 Tomcat 上,演示了 OAuth2 的实际运行过程。 **例子改造说明** - **创建 JDBC 表**:...
SqlSessionFactoryBean提供了配置数据源、配置MyBatis的配置文件路径等能力,使得SqlSessionFactory的创建过程完全在Spring的控制之下。 2. **MapperScannerConfigurer**: 这个类用于扫描应用中的Mapper接口,并...
4. **springcloud-service**:同样是一个目录,可能包含了某个微服务的实现,比如一个具体业务的服务,它会实现服务接口并注册到 Eureka。 5. **springcloud-eureka**:这个目录可能包含了 Eureka 服务的配置和实现...
4. **创建Jersey Application子类**:在`MyApplication`类中,你需要注册Spring的ContextResolver,以便Jersey能从Spring容器中查找bean: ```java public class MyApplication extends ResourceConfig { public ...