引入起步依赖 → 配置yaml属性 → Spring Boot自动创建Bean
即:起步依赖 + yaml配置 = 自动创建Bean
XML
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-amqpartifactId>
dependency>
YAML
# 配置属性
spring:
rabbitmq:
host: 192.168.28.26
port: 5672
username: itcast
password: 123321
virtual-host: /
publisher-confirm-type: correlated
publisher-returns: true
template:
mandatory: true
自动创建的Bean:
RabbitTemplate
ConnectionFactory
RabbitAdmin
MyBatis
自动生成的Bean:SqlSessionFactory, SqlSessionTemplate, DataSource
Redis
自动生成的Bean:RedisTemplate, StringRedisTemplate, LettuceConnectionFactory
Web
自动生成的Bean:DispatcherServlet, HandlerMapping, HandlerAdapter
JPA
自动生成的Bean:EntityManagerFactory, JpaTransactionManager
两者在Bean生命周期中的位置:实例化—>用户属性赋值—>容器属性赋值
更完整的Bean生命周期参考链接:Bean完整生命流程
用户属性赋值(配置属性绑定)
将yaml/properties配置文件中的配置值直接赋值到Bean的对应属性中。这是一个单纯的值拷贝过程,将外部配置文件中的字符串、数字、布尔值等基本数据类型绑定到Bean的属性上。
特点:
@ConfigurationProperties
注解 + Spring的配置属性绑定器容器属性赋值(依赖注入)
将Spring容器中已经创建好的Bean对象注入到当前Bean的属性中。这是Bean与Bean之间的对象引用关系建立,实现了组件之间的依赖关系。
特点:
@Autowired
、@Resource
等注解 + Spring的依赖注入器两者对比总结
特征 | 用户属性赋值 | 容器属性赋值 |
---|---|---|
本质 | 配置值拷贝 | 对象引用注入 |
数据类型 | 基本数据类型、字符串 | Bean对象 |
数据来源 | 外部配置文件 | Spring容器 |
关系建立 | 配置与Bean的绑定 | Bean与Bean的依赖关系 |
核心区别: 用户属性赋值是"值的传递",容器属性赋值是"引用的传递"。
配置文件
myapp:
name: "我的应用"
port: 8080
enabled: true
属性赋值
@Component
@ConfigurationProperties(prefix = "myapp")
public class MyAppProperties {
private String name;
private int port;
private boolean enabled;
// Spring会调用这些setter进行用户属性赋值
public void setName(String name) { this.name = name; }
public void setPort(int port) { this.port = port; }
public void setEnabled(boolean enabled) { this.enabled = enabled; }
}
@Service
public class OrderService {
private UserService userService; // ← 需要容器属性赋值
private PaymentService paymentService; // ← 需要容器属性赋值
// Spring会调用这个构造函数进行容器属性赋值
public OrderService(UserService userService, PaymentService paymentService) {
this.userService = userService; // ← 容器属性赋值
this.paymentService = paymentService; // ← 容器属性赋值
}
}
核心观点: 所有Aware接口在技术实现上都是相同的,都是回调接口,只是通过命名进行语义化区分,明确实现该接口对应的函数对应的职责
类比@Componen
Aware接口同理:
本质相同,但语义化命名
Aware接口的统一模式
// 所有Aware接口都遵循这个模式
public interface XxxAware {
void setXxx(Xxx xxx); // 回调方法
}
// Spring源码简化版
public class AbstractAutowireCapableBeanFactory {
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
// 所有Aware接口的处理逻辑都类似
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(this);
}
// ... 其他Aware接口处理逻辑相同
}
}
}
当需要使用第三方Bean时,需要对Bean进行额外的配置,这时候可以使用Aware接口对SpringBoot自动装配的Bean进行配置或者直接重新生成Bean
@Slf4j
@Configuration
public class CommonConfig implements ApplicationContextAware {
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
// 通过Bean容器获取Spring Boot自动创建的Bean
RabbitTemplate rabbitTemplate = applicationContext.getBean(RabbitTemplate.class);
// 对现有Bean进行修改和功能增强
rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> {
log.error("消息发送到队列失败,响应码: {},失败原因:{},交换机:{},路由key:{},消息:{}",
replyCode, replyText, exchange, routingKey, message);
});
}
}
@Configuration
public class RabbitConfig {
@Bean
@Primary // 解决Bean冲突
public RabbitTemplate customRabbitTemplate(
ConnectionFactory connectionFactory,
@Autowired(required = false) RabbitTemplateConfigurer configurer) {
RabbitTemplate template = new RabbitTemplate(connectionFactory);
// 应用Spring Boot的默认配置
if (configurer != null) {
configurer.configure(template, connectionFactory);
}
// 设置mandatory=true,否则ReturnCallback不会触发
template.setMandatory(true);
// 自定义配置
template.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> {
log.error("消息发送到队列失败,响应码: {},失败原因:{},交换机:{},路由key:{},消息:{}",
replyCode, replyText, exchange, routingKey, message);
});
return template;
}
}
特征 | Aware接口修改 | 重新生成Bean |
---|---|---|
Bean数量 | 1个(修改现有) | 可能2个 |
配置复杂度 | 简单 | 复杂(需要处理自动配置) |
学习成本 | 低 | 高 |
风险程度 | 低 | 中(可能配置冲突) |
灵活性 | 中 | 高 |
适用场景 | 简单定制 | 复杂定制、生产环境 |
由Spring Boot自动创建的第三方Bean一般带有@ConditionalOnMissingBean注解,这个注解的作用是只有当容器中没有这个类型(默认是类型,可以改为按照名称)的Bean时,才创建
比如:
@Bean
@ConditionalOnMissingBean // 关键条件
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
}
翻译成白话: 如果Spring容器中还没有RabbitTemplate
类型的Bean,那我就创建一个;如果已经有了,那我就不创建了,避免冲突。
但是出于某些原因,并不是所有的第三方Bean都会有这个注解,此时如果再自己创建就可能会出现依赖冲突的问题
解决方案:
在自定义Bean上同时添加@Primary注解,确保冲突时会注入自己的Bean
@Bean
@Primary // 明确指定优先级
public RabbitTemplate customRabbitTemplate(...) {
// 确保注入时使用这个Bean
}
@Bean("myRabbitTemplate") // 使用特定名称
public RabbitTemplate customRabbitTemplate(...) { ... }
@Service
public class MessageService {
@Autowired
@Qualifier("myRabbitTemplate") // 明确指定注入哪个Bean
private RabbitTemplate rabbitTemplate;
}
@SpringBootApplication(exclude = {RabbitAutoConfiguration.class}) //完全禁用RabbitMQ自动配置
public class Application {
// 只使用自己的配置
}
如果使用自己定义的Bean,不使用Spring自动创建的Bean,并且不显式的应用Spring Boot的默认配置,使用就会丢失Spring Boot的配置属性自动绑定)功能,即无法自动赋值yaml文件中定义的属性了,这部分属性也需要自己设置,一不小心就有可能丢失某些配置,比如: