新闻详情

新闻详情

首页 / 资讯中心 / 详情

将自己 new 的对象纳入 IoC 容器管理详解

发布时间:2026/9/28 4:45:41来源:尧图网络
将自己 new 的对象纳入 IoC 容器管理详解
将自己 new 的对象纳入 IoC 容器管理详解一、为什么需要这样做正常情况下Spring 管理的 Bean 由容器负责创建依赖注入、AOP 代理、生命周期回调都会自动生效。但有些场景下对象是由我们手动new出来的从数据库读取配置后动态创建对象根据用户输入决定创建哪种实现使用 Builder 模式构建复杂对象在工具类或静态方法中创建对象这些对象默认不受 Spring 管理拿不到注入的依赖也不会被 AOP 增强。如果希望它们享受 Spring 的能力就需要把它们“交给”容器处理。二、核心工具AutowireCapableBeanFactorySpring 提供了一个接口AutowireCapableBeanFactory专门用于对容器外的对象进行依赖注入和初始化。它定义了三个核心方法方法作用autowireBean(Object)对对象进行依赖注入但不执行初始化回调autowireBeanProperties(Object, int, boolean)按指定模式注入属性initializeBean(Object, String)执行 Aware 回调、BeanPostProcessor、初始化方法createBean(Class)创建并完整初始化一个 BeanApplicationContext本身没有直接暴露这些方法需要通过getAutowireCapableBeanFactory()获取。三、方案一autowireBean initializeBean这是最常用的方式。先注入依赖再执行初始化。ComponentpublicclassBeanManagerimplementsApplicationContextAware{privateAutowireCapableBeanFactorybeanFactory;OverridepublicvoidsetApplicationContext(ApplicationContextcontext){this.beanFactorycontext.getAutowireCapableBeanFactory();}publicTTregisterBean(TexistingBean){// 1. 依赖注入beanFactory.autowireBean(existingBean);// 2. 执行 Aware 回调、BeanPostProcessor、初始化方法return(T)beanFactory.initializeBean(existingBean,existingBean.getClass().getSimpleName());}}使用MyServiceservicenewMyService();// 手动 newbeanManager.registerBean(service);// 交给 Spring 处理service.doSomething();// 此时依赖已注入AOP 已生效autowireBean()会处理Autowired、Value、Resource注解把容器中匹配的 Bean 注入到目标对象的字段和方法中。initializeBean()会依次执行Aware 接口回调BeanNameAware、BeanFactoryAware等BeanPostProcessor.postProcessBeforeInitialization()PostConstruct、InitializingBean.afterPropertiesSet()、init-methodBeanPostProcessor.postProcessAfterInitialization()AOP 代理在此生成注意initializeBean()返回的可能是代理对象所以要用返回值而不是原对象。MyServiceservicenewMyService();MyServiceprocessed(MyService)beanFactory.initializeBean(service,myService);// 使用 processed而不是 service四、方案二createBean如果对象还没有创建可以直接让 Spring 创建并完整初始化MyServiceservicebeanFactory.createBean(MyService.class);这种方式会走完整的 Bean 创建流程实例化、属性填充、初始化、AOP 代理。但它不会把 Bean 注册到容器中每次调用都创建新实例相当于一个“受 Spring 管理的 prototype”。五、方案三通过 Bean 方法如果对象是在配置类中创建的可以直接用Bean方法返回ConfigurationpublicclassAppConfig{BeanpublicMyServicemyService(){MyServiceservicenewMyService();// 手动设置一些属性service.setName(自定义);returnservice;// Spring 会管理这个 Bean}}Bean方法返回的对象会被 Spring 完整管理依赖注入、AOP、生命周期回调都会生效。这是最简洁的方式适合静态的、启动时就能确定的对象。但Bean方法在容器启动时执行无法在运行时动态创建对象。如果对象需要根据运行时参数创建就得用AutowireCapableBeanFactory。六、方案四registerSingleton 动态注册如果希望动态创建的对象被注册到容器中成为真正的单例 Bean可以用DefaultListableBeanFactory.registerSingleton()ComponentpublicclassDynamicBeanRegistrarimplementsApplicationContextAware{privateDefaultListableBeanFactorybeanFactory;OverridepublicvoidsetApplicationContext(ApplicationContextcontext){this.beanFactory(DefaultListableBeanFactory)context.getAutowireCapableBeanFactory();}publicvoidregisterDynamicBean(Stringname,Objectbean){// 先处理依赖注入和初始化beanFactory.autowireBean(bean);beanFactory.initializeBean(bean,name);// 再注册为单例beanFactory.registerSingleton(name,bean);}}注册后其他 Bean 可以通过Autowired或getBean()获取这个动态注册的 Bean。注意registerSingleton()注册的 Bean 不参与BeanPostProcessor的完整处理流程某些扩展点可能不生效。如果需要完整处理建议用方案一。七、方案五Configurable AspectJ这是最“无感”的方式。通过 AspectJ 编译期织入让new出来的对象自动获得依赖注入。ConfigurablepublicclassMyService{AutowiredprivateUserDaouserDao;publicvoiddoSomething(){userDao.save();}}配置 AspectJcontext:spring-configured/context:load-time-weaver/这种方式对代码有侵入需要加Configurable且需要 AspectJ 编译期或加载期织入支持配置复杂。适合大量手动new对象的场景但日常开发中很少使用。八、各方案对比方案适用场景是否注册到容器依赖注入AOP 代理复杂度autowireBeaninitializeBean运行时动态创建对象否✅✅中createBean让 Spring 创建新实例否✅✅低Bean方法启动时静态创建是✅✅低registerSingleton动态注册为单例是✅⚠️中Configurable AspectJ大量手动 new否✅✅高九、常见问题1. 注入的依赖为 null如果用new创建对象后直接使用没有调用autowireBean()依赖字段就是null。必须显式交给AutowireCapableBeanFactory处理。2. AOP 代理不生效autowireBean()只做依赖注入不做 AOP 代理。必须调用initializeBean()AOP 代理在postProcessAfterInitialization中生成。且要使用返回值而不是原对象。3. 循环依赖问题手动创建的对象如果依赖其他 Bean而其他 Bean 又依赖它可能产生循环依赖。由于手动创建的对象不在三级缓存中循环依赖无法自动解决。4. 销毁回调不执行手动创建的对象不会注册到disposableBeans容器关闭时不会执行PreDestroy。需要手动处理销毁逻辑。5. registerSingleton 的时机registerSingleton()必须在容器刷新完成后调用。在BeanFactoryPostProcessor或BeanDefinitionRegistryPostProcessor中调用可能无效因为此时容器还没完全初始化。十、完整示例ComponentpublicclassDynamicBeanManagerimplementsApplicationContextAware{privateAutowireCapableBeanFactorybeanFactory;OverridepublicvoidsetApplicationContext(ApplicationContextcontext){this.beanFactorycontext.getAutowireCapableBeanFactory();}publicTTcreateAndManage(ClassTclazz){try{// 1. 手动 newTinstanceclazz.getDeclaredConstructor().newInstance();// 2. 依赖注入beanFactory.autowireBean(instance);// 3. 初始化 AOP 代理return(T)beanFactory.initializeBean(instance,clazz.getSimpleName());}catch(Exceptione){thrownewRuntimeException(创建 Bean 失败,e);}}}使用ServicepublicclassOrderService{AutowiredprivateDynamicBeanManagerbeanManager;publicvoidprocess(){// 动态创建并管理PaymentServicepaymentbeanManager.createAndManage(AliPayService.class);payment.pay(100);// 依赖已注入AOP 已生效}}十一、总结维度核心要点核心工具AutowireCapableBeanFactory依赖注入autowireBean()初始化 AOPinitializeBean()使用返回值注册到容器registerSingleton()静态创建Bean方法无感方案Configurable AspectJ注意事项销毁回调不执行、循环依赖无法自动解决、registerSingleton 的时机把自己new的对象纳入 IoC 容器管理核心思路是借助AutowireCapableBeanFactory补上 Spring 容器原本在创建 Bean 时做的处理。理解autowireBean()和initializeBean()的分工就能灵活地在运行时动态管理对象同时享受 Spring 的依赖注入和 AOP 能力。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

Leiningen Profiles 完全指南:声明、合并、激活与调试项目配置 2026/9/28 8:42:06

Leiningen Profiles 完全指南:声明、合并、激活与调试项目配置

构建工具CLI 【免费下载链接】leiningen Moved to Codeberg; this is a temporary convenience mirror 项目地址: https://gitcode.com/gh_mirrors/le/leiningen 点击查看 免费下载 Leiningen 的 Profiles(配置文件/配置档)机制让你可以按场…

阅读更多 →
Android APK免费加固实战:从DEX加密到签名校验的完整指南 2026/9/28 8:41:53

Android APK免费加固实战:从DEX加密到签名校验的完整指南

1. 为什么加固:你的APK在别人眼里几乎等于透明先聊个现实问题。我见过太多开发者,花几个月做完一个App,功能稳定、体验不错,结果上线没几天,市场上就出现了带广告插件的"盗版版"——UI是自己的,代…

阅读更多 →
Apache SeaTunnel Kafka Sink 连接器实战指南:配置详解、消息分区与 Exactly-Once 语义 2026/9/28 8:41:53

Apache SeaTunnel Kafka Sink 连接器实战指南:配置详解、消息分区与 Exactly-Once 语义

数据工程大数据批处理流处理 【免费下载链接】seatunnel SeaTunnel is a next-generation super high-performance, distributed, massive data integration tool. 项目地址: https://gitcode.com/gh_mirrors/sea/seatunnel 点击查看 免费下载 Apache SeaTunnel 的…

阅读更多 →
高通Firehose文件深度解析:从EDL引导原理到修改实战 2026/9/28 8:41:53

高通Firehose文件深度解析:从EDL引导原理到修改实战

1. 玩机底层逻辑:为什么Firehose文件是绕不开的核心玩机玩到一定深度,你迟早会碰到一个叫prog_firehose.mbn的文件。它藏在大多数高通平台机型的固件包深处,名字看起来像天书,但作用极其关键——它是设备进入EDL(Emerg…

阅读更多 →
CTF笔记2-编码基础 2026/9/28 8:41:53

CTF笔记2-编码基础

一、编码与解码核心概念 1. 编码(Encode) 定义:将原始可读信息(文字、数字、二进制数据)按照一套公开固定规则,转换为另一套字符 / 二进制串的过程。 三大作用: 网络传输兼容:二进…

阅读更多 →
Marlin串口配置实战:断连丢包一次修好 2026/9/28 8:41:53

Marlin串口配置实战:断连丢包一次修好

Marlin串口配置实战:断连丢包一次修好 【免费下载链接】Marlin Marlin is a firmware for RepRap 3D printers optimized for both 8 and 32 bit microcontrollers. Marlin supports all common platforms. Many commercial 3D printers come with Marlin installed…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉