thedarklord47
thedarklord47

Reputation: 3312

SpEL: get current bean name during bean instantiation

I am attempting to use SpEL to get the name of the bean currently being instantiated to allow multiple beans of same class to be created with different properties supplied by @PropertySource. I am hoping for something like the following:

public class SampleBean {
    @Value("${#{CurrentBeanName}.val}")
    private String val
}

Other bean:

public class OtherBean {

    @Autowired
    @Qualifier(name="BeanA")
    SampleBean beanA;

    @Autowired
    @Qualifier(name="BeanB")
    SampleBean beanB;
}

properties file:

BeanA.val=VALUE A
BeanB.val=VALUE B

If I add beanName=BeanA to my properties file, I am able to get this to work with

@Value("${${beanName}.val}")

Any ideas on what to do for #{BeanName}? If this is impossible then so be it, but if it works it would be much cleaner than my current solution.

EDIT:

Or any way to pass a constant from the xml bean definition to SpEL? example:

<bean id="BeanA" class="...">
    <property name="prefix" value="BeanA"/>
</bean>

java:

public class SampleBean {
    @Value("${#{prefix}.val}")
    private String val
}

Any sort of attribute or anything would work

EDIT2:

This is trivial in old XML based config

spring.xml:

<bean id="beanA" class="SampleBean">
    <property name="val" value="${BeanA.val}"/>
</bean>
<bean id="beanB" class="SampleBean">
    <property name="val" value="${BeanB.val}"/>
</bean>

SampleBean.java:

public class SampleBean {

    private String val;

    public void setVal (String val) {
        this.val = val;
    }
}

However when switching to the new @Value annotations to get rid of all the setters, it seems non-singletons with diff properties aren't supported (i.e. no way to dynamically filter @Value arguments on bean creation)

Upvotes: 0

Views: 2396

Answers (2)

Gary Russell
Gary Russell

Reputation: 174664

No; it is not possible to reference the current bean.

EDIT

To address your comment below, the Java Configuration equivalent of

<bean id="BeanA" class="com.my.Foo">
    <property name="prefix" value="BeanA"/>
</bean>

is

@Bean
public Foo BeanA() {
    Foo a = new Foo();
    a.setPrefix("BeanA");
}

although, by convention, you'd probably name it beanA.

Upvotes: 1

Derrops
Derrops

Reputation: 8127

If you have singleton bean types you could just use a static final variable for the name and then reference that. But the bigger issue is that you will be breaking the Spring inversion of control principals if you begin depending on Spring bean names, which is why this sort of thing isn't done. Pretty much want to focus on creating modules and domains for your project. If you begin accessing components coming from the Spring Context directly (such as the bean name) you will find that your modules will become brittle, hard to change and very hard to reason about as they begin to depend on behaviour from seemingly unrelated modules, such as the Spring Dependency Injection Framework. Although you may have a valid use-case for doing this you just need to be very very careful.

Upvotes: 0

Related Questions