spring的bean注入无效和new创建对象的区别

探讨了在Java中手动new对象与通过Spring容器管理对象的区别,特别是在@Autowired注解的有效性上。说明了如何正确配置Spring组件以实现依赖注入。

注意!如果直接new的话,类里面的autowire将不生效

项目中用到如下代码
然后 在运行的时候发现 通过 @Autowired注入的对象 capitalDetailDOMapper和 excelRecordDOMapper的值为null
public class ExcelListener extends AnalysisEventListener<List> {
@Autowired
private CapitalDetailDOMapper capitalDetailDOMapper;
@Autowired
private ExcelRecordDOMapper excelRecordDOMapper;

}

刚开始以为是ExcelListener没有加bean扫描注解导致的
于是加上后
@Component
public class ExcelListener extends AnalysisEventListener<List> {
@Autowired
private CapitalDetailDOMapper capitalDetailDOMapper;
@Autowired
private ExcelRecordDOMapper excelRecordDOMapper;

}

结果在运行的时候,两个mapper,仍然为null。

检查代码发现
在ExcelListener这个类的使用场景中,是 ExcelListener excelListener= new ExcelListener(); 创建的对象
在这里插入图片描述

这里就明白了, 手动通过new创建和通过spring容器创建管理对象是不一样的,手动new的对象,内部用@autowire注解是无效的。

若让该autowire生效,则需要通过容器来管理对象
改造如下,先给ExcelListener加上注解@Component
@Scope(“prototype”)
@Component(“excelListener”)
public class ExcelListener extends AnalysisEventListener<List> {
@Autowired
private CapitalDetailDOMapper capitalDetailDOMapper;
@Autowired
private ExcelRecordDOMapper excelRecordDOMapper;

}

这样 这个bean就会被加载到spring容器中,这里Scope表示bean的作用范围,spring默认创建的对象是单例的
prototype是非单例,这里我主要是想在不同的线程里面创建不同的ExcelListener实例。
可以通过容器获取bean,也可以直接@autowire
ExcelListener excelListener= SpringBeanUtils.getBean(“excelListener”);

其中SpringBeanUtils为实现了BeanFactoryPostProcessor接口的实现类
能够从spring容器里面获取到bean的实例,如果bean是非单例的 每次则获取到是一个新的bean

@Component
@Getter
public class SpringBeanUtils implements BeanFactoryPostProcessor {
private static ConfigurableListableBeanFactory beanFactory;
public static T getBean(String beanName) {
return (T) beanFactory.getBean(beanName);
}
public static T getBean(Class beanClz) {
return beanFactory.getBean(beanClz);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
SpringBeanUtils.beanFactory = beanFactory;
}
}

注意!!如果A类是单例的,那么A类中的成员B类声明为非单例的,也是无效的。
因为只有A类的一个实例,里面包含的B类的实例也只有一个。 除非能再次创建A类的实例,才能创建出另一个B类的实例对象。

<think>好的,我现在要解决用户的问题:“一定要注入Spring Bean才可以实现BeanFactoryPostProcessor接口吗?”首先,我需要理解用户的问题核心。用户想知道是否必须将实现了BeanFactoryPostProcessor的类注册为Spring Bean才能使其生效。 首先,我回忆一下Spring框架中BeanFactoryPostProcessor的作用。BeanFactoryPostProcessor是用来在Spring容器加载了Bean的定义之后,但在Bean实例化之前,对Bean的配置元数据进行修改的接口。常见的例子是PropertySourcesPlaceholderConfigurer,它用来处理占位符配置。 接下来,我需要确认BeanFactoryPostProcessor的实现是否需要被Spring容器管理。根据Spring的文档,BeanFactoryPostProcessor本身必须是一个Bean,由Spring容器实例化调用。因为Spring在启动时,会扫描所有Bean定义,找到实现了BeanFactoryPostProcessor的类,并在合适的时机调用它们的postProcessBeanFactory方法。 用户可能的问题在于,是否可以不通过Spring的依赖注入,而是手动创建该类的实例,然后注册到容器中。比如,通过new关键字创建实例,然后调用某个方法将其添加到容器。但根据Spring的设计,BeanFactoryPostProcessor的实现必须作为Bean存在,否则Spring无法自动检测并执行它们。 不过,可能存在特殊情况,比如编程式地向Spring容器添加BeanFactoryPostProcessor。例如,在基于Java配置的情况下,可以通过实现BeanDefinitionRegistryPostProcessor来动态注册Bean定义,包括BeanFactoryPostProcessor。但这实际上还是在Spring的上下文管理范围内,并没有脱离Bean的范畴。 另外,用户可能有误解,认为实现某个接口必须通过@Component或其他注解注入,但实际上,无论通过XML配置、Java配置还是组件扫描,只要该实现类被定义为Spring Bean,就会被容器处理。因此,关键在于是否被Spring管理,而不是注入的方式。 可能用户遇到的场景是,他们尝试手动创建了一个BeanFactoryPostProcessor的实例,但没有将其注册为Bean,导致功能未生效。因此需要明确告知必须将其注册为Bean,无论是通过哪种方式。 总结:必须将BeanFactoryPostProcessor的实现类注册为Spring Bean,否则Spring容器不会自动调用其方法。可以通过XML、Java配置或组件扫描等方式注册,但必须作为Bean存在。</think>--- ### 分步说明:实现 `BeanFactoryPostProcessor` 是否必须注册为 Spring Bean? #### **1. 核心结论** **必须将 `BeanFactoryPostProcessor` 的实现类注册为 Spring Bean**,否则 Spring 容器无法识别并触发其逻辑。 --- #### **2. 原因分析** - **Spring 的扩展机制**: `BeanFactoryPostProcessor` 是 Spring 容器的扩展点,用于修改 Bean 定义(`BeanDefinition`)。Spring 容器启动时,会**自动扫描所有 Bean**,找出实现了该接口的类,并在**Bean 实例化前**调用其 `postProcessBeanFactory` 方法。 - **依赖容器管理**: 若未将实现类注册为 BeanSpring 不会主动发现它,也无法调用其逻辑。即使手动实例化该对象,也无法直接注入到容器流程中。 --- #### **3. 验证方式** ##### 示例代码:显式注册为 Bean ```java // 实现 BeanFactoryPostProcessor public class MyPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { System.out.println("修改 Bean 定义..."); } } // 配置类中注册为 Bean @Configuration public class AppConfig { @Bean public MyPostProcessor myPostProcessor() { return new MyPostProcessor(); } } ``` ##### 若未注册为 Bean ```java // 未通过 @Component 或 @Bean 注册 public class InvalidPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(...) { System.out.println("这段代码永远不会执行!"); } } ``` **结果**:Spring 不会调用 `InvalidPostProcessor` 的方法。 --- #### **4. 特殊场景:编程式注入** 可通过 `BeanDefinitionRegistryPostProcessor` 动态注册 `BeanFactoryPostProcessor`,但本质仍是**间接将其变为 Bean**: ```java public class DynamicRegistry implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanFactory(...) {} @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { // 动态注册 MyPostProcessor 的 Bean 定义 AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder .genericBeanDefinition(MyPostProcessor.class) .getBeanDefinition(); registry.registerBeanDefinition("myPostProcessor", beanDefinition); } } ``` --- #### **5. 常见误区** - **手动实例化无效**: ```java // 错误示例:手动 new 对象不会生效 BeanFactoryPostProcessor processor = new MyPostProcessor(); processor.postProcessBeanFactory(beanFactory); // 无意义 ``` Spring 容器的生命周期管理是自动化的,手动调用无法插入到正确流程中。 - **静态工具类无法替代**: 即使通过静态方法修改 Bean 定义,也无法替代 `BeanFactoryPostProcessor` 的标准扩展点。 --- ### **总结** - **必须条件**:`BeanFactoryPostProcessor` 的实现类必须通过 SpringBean 管理机制(如 `@Component`、`@Bean`、XML 配置)注册到容器中。 - **底层原理**:Spring 在初始化阶段会主动遍历所有 Bean,筛选并调用符合条件的扩展点实现。 - **灵活场景**:可通过编程式注册动态添加,但最终仍需将其定义为 Bean
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值