当前位置: 首页 > 面试题库 >

使用Java Config覆盖自动装配设定器

益何平
2023-03-14
问题内容

考虑以下类别:

public class MyBean {
    private A a;

    @Autowired(required=true)
    public void setA(A a) {
        this.a = a;
    }

    public A getA() {
        return a;
    }
}

在某些情况下,需要覆盖自动装配的注射,例如,当Spring无法找到单个注射候选物时。在XML中,我可以有以下示例:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="first" class="my.pkg.AImpl"/>
    <bean id="second" class="my.pkg.AImpl"/>
    <bean id="myBeanFirst" class="my.pkg.MyBean">
        <property name="a" ref="first"/>
    </bean>
    <bean id="myBeanSecond" class="my.pkg.MyBean">
        <property name="a" ref="second"/>
    </bean>

</beans>

有没有办法用Java
Config做同样的事情?以下内容不起作用(我理解原因),因为Spring尝试从myBean方法返回后尝试自动装配该属性,并且该属性失败,并显示NoUniqueBeanDefinitionException:

@Configuration
public class MyConfig {
    @Bean
    public A first() {
        return new AImpl();
    }

    @Bean
    public A second() {
        return new AImpl();
    }

    @Bean
    public MyBean myBeanFirst(A first) {
        MyBean myBean = new MyBean();
        myBean.setA(first);
        return myBean;
    }

    @Bean
    public MyBean myBeanSecond(A second) {
        MyBean myBean = new MyBean();
        myBean.setA(first);
        return myBean;
    }
}

修改MyBean类并不总是一种选择,例如,因为它来自外部库。这是我必须使用XML配置的情况吗?

谢谢,Andrea Polci

更新 感谢您提供这两种解决方案(按名称注入和使用@Primary),但是它们不能解决我的用例,因此我认为我需要更具体。

在我的用例中,MyBean类来自外部库,因此无法对其进行任何更改。我还需要有多个MyBean实例,每个实例都注入A接口的不同实例。我已经更新了上面的代码以反映这一点(xml和java)。

有使用java
config的解决方案吗?是否可以避免依赖MyBean的依赖自动装配?(仅在该类的bean上,而不是为上下文中的每个bean完全禁止自动装配)


问题答案:

可以,我相信这个答案会满足您的需求。

我们需要的一个实现MergedBeanDefinitionPostProcessor将为aclass
的属性设置正确的值MyBean。可以通过以下课程来完成

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.stereotype.Component;


@Component
public class MyBeanPostProcessor implements MergedBeanDefinitionPostProcessor {


    @Override
    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
        if(beanName.equals("myBeanFirst")) {
            beanDefinition.getPropertyValues().add("a", getMyBeanFirstAImpl());
        }
        else if(beanName.equals("myBeanSecond")) {
            beanDefinition.getPropertyValues().add("a", getMyBeanSecondAImpl());
        }
    }

    private Object getMyBeanFirstAImpl() {
        return new AImpl();
    }

    private Object getMyBeanSecondAImpl() {
        return new AImpl();
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

如您所见,这里的bean名称是硬编码的,但是可以在静态最终String中设置它们,以下代码中的@Bean批注也将使用它们

@Configuration
public class Configuration {



    @Bean
    public MyBean myBeanFirst() {
        return new MyBean();
    }

    @Bean
    public MyBean myBeanSecond() {
        return new MyBean();
    }

}

您将在以下代码中注意到,在MyBean创建方法中未调用setA,因为无论设置的值(在这种情况下未设置)在Spring执行bean后处理器时都将被覆盖。

如果您需要A的默认值(例如,要将其注入其他bean),请继续在先前的配置中定义一个@Bean



 类似资料:
  • 与以下属性相关联,但它并没有更好地工作 我该怎么办?

  • 问题内容: 有没有一种简单的方法可以轻松地在特定的单元测试中覆盖自动装配的Bean?编译类中每种类型只有一个bean,因此在这种情况下自动装配不是问题。测试类将包含其他模拟。运行单元测试时,我只想指定一个基本的附加配置,运行该单元测试时,请使用此模拟而不是标准Bean。 概要文件似乎对我的需求有些矫kill过正,而且我不确定使用主要注解是否可以实现,因为不同的单元测试可能具有不同的模拟。 问题答案

  • 我正在努力用我的自定义php覆盖php cli配置。伊尼 我的定制php.ini 运行php cli 输出 然而,自定义php.ini似乎没有覆盖max_execution_timesafe_mode,因为它输出0和On而不是90和off。 运行这个简单的脚本 输出默认cli配置(128M),而不是预期的256M。 运行这个简单的脚本 按预期产出90。 到目前为止,我只在运行时覆盖了一个配置指令,

  • 问题内容: 我想要的只是让bool(myInstance)返回False(以及在if / or / and等条件下让myInstance评估为False。我知道如何覆盖>,<,=) 我已经试过了: 有什么建议? (我正在使用Python 2.6) 问题答案: 这是Python 2.x还是Python 3.x?对于Python 2.x,您正在寻找替代方法。

  • 在苹果自带地图和百度地图上覆盖一层图片,图片可以随地图缩放移动。关键就是自定义Overlay和OverlayView。 作者说:实在无力吐槽了,百度地图iOS SDK中的静态库文件居然都是10M !由于过大上传不了,亲们自行去 http://developer.baidu.com/map/sdk-ios.htm 按提示添加SDK吧!至于基于百度地图的自定义Overlay和OverlayView 记

  • 问题内容: 我在Employee类中有以下定义 现在,我想使用现有员工ID导入现有员工。即使在保存之前设置了员工ID,也会忽略分配的ID,并存储自动递增的ID。我们如何覆盖呢? 问题答案: 我编写了自己的生成器来解决此问题。 并像这样使用它:(替换包名)