SpringBean装配非主流用法——给已存在的对象设置属性

本文讨论了如何在Java代码中通过运行时注入依赖,以及如何避免潜在的依赖注入错误。通过创建ApplicationContext并手动注册bean,实现对象依赖的注入。同时提供了两种解决方法:一种是将依赖注入提前暴露在Spring Bean配置文件中,另一种是明确指定可以注入的依赖名称或类型,确保在运行时依赖注入的稳定性和可预测性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

适用情况:
java代码里获得了一个对象,反序列化来的或者直接new的还是set进来的无所谓,这个对象依赖于ApplicationContext中配置的一些bean,需要注入依赖的bean。对象的具体类型未知,依赖哪些bean不确定。

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.support.FileSystemXmlApplicationContext;
 
public class AutowireBeanProperties {
    public static void main(String[] args) throws Exception {
        /*
         * 创建ApplicationContext,这里为了简单示例就不写xml文件而是用代码构建了。
         * 下面的代码相对于xml文件里有这么个bean:
         * <bean id="component" class="AutowireBeanProperties.ComponentImpl" />
         */
        final ComponentImpl component = new ComponentImpl();
        FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext();
        context.addBeanFactoryPostProcessor(new BeanFactoryPostProcessor() {
             
            @Override
            public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
                beanFactory.registerSingleton("component", component);
            }
        });
        context.refresh();
        /*创建ApplicationContext结束*/
        ComponentAware componentAware = new ComponentAware();
        context.getBeanFactory().autowireBeanProperties(componentAware, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, false);
        System.out.println(componentAware.getComponent() == component);
        context.close();
    }
     
    public static interface Component {
         
    }
     
    public static class ComponentImpl implements Component {
         
    }
    public static class ComponentAware {
        private Component component;
        public Component getComponent() {
            return component;
        }
        public void setComponent(Component component) {
            this.component = component;
        }
    }
}

直接把autowireBeanProperties方法文档复制过来:

Autowire the bean properties of the given bean instance by name or type. Can also be invoked with AUTOWIRE_NO in order to just apply after-instantiation callbacks (e.g. for annotation-driven injection).

Does not apply standard BeanPostProcessors callbacks or perform any further initialization of the bean. This interface offers distinct, fine-grained operations for those purposes, for example initializeBean. However, InstantiationAwareBeanPostProcessor callbacks are applied, if applicable to the configuration of the instance.

这个方法只设置对象的属性,AutowireCapableBeanFactory.configureBean方法会做更多事情,具体的看spring文档。

存在的问题
一个对象如果要这样装配注入依赖,就会和SpringBean配置文件产生不明显的依赖关系。AUTOWIRE_BY_NAME的话就依赖于配置文件中的bean id;AUTOWIRE_BY_TYPE则会依赖于bean类型。
而且这样的依赖不明显,可能修改一下SpringBean配置文件,然后某个看起来完全不相关的地方的代码就因为依赖注入失败挂了。

解决办法 
1:让问题提前暴露
在SpringBean配置文件里显示的配置一个需要运行时注入依赖的对象, 设置autowire属性,让Spring自动装配它,然后写一个类实现org.springframework.beans.factory.InitializingBean接口,在Spring装配完对象后检查依赖注入是否完整。
这样就能提前发现会出现的依赖注入失败问题。
2:明确可以注入的依赖的名称/类型
从上面的代码可以看出,是可以在没有xml文件的情况下创建一个ApplicationContext的,然后把可以注入的依赖全部加入到ApplicationContext里,只用这个ApplicationContext来做运行时依赖注入。从而可以保证所有约定的可以注入的依赖都是存在的,bean id也都是确定的。


转载于:https://my.oschina.net/guyongquan/blog/495817

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值