Will the instances stored in the map inside the factory be spring managed bean?
Making the FruitFactory
a managed bean
@Bean
public FruitFactory fruitFactory() {
return new FruitFactory();
}
doesn't make any of the objects it's referring to managed beans. However, this
@Bean
public Fruit getFruit() {
return fruitFactory().getFruit(fruitType);
}
does make that one returned Fruit
a managed bean. @Bean
marks a method as a bean definition and bean factory (it creates the bean). The object you return will be managed by Spring's bean life cycle.
Is there any issue with the implementation?
It seems weird that you're creating a FruitFactory
bean but also a Fruit
from that same FruitFactory
. Are you even going to inject the FruitFactory
elsewhere in the application?
I was trying to implement it in a better way, so that when a new fruit comes, I don't have to modify my factory
Seriously, your factory is messing everything up. Spring already does its job, and more! Annotations make your life easier. You can give an identifier to the @Bean
. You can qualify the bean with @Qualifier
(and then also qualify the injection target with @Qualifier
). You can set a @Profile
for when and under which conditions the bean should be initialized.
But the issue is when and how the subclasses will be loaded? I'll not be using the classes, not before putting their instances into the map. Can anyone suggest a better way?
You can use bean initMethod
s, which you specify as a @Bean
annotation attribute, or a @PostConstruct
annotated method to do post-initialization logic. You can use these to register the beans with the factory, which you'll have injected (but that design doesn't sound right to me, you'd have to show us more.)
You should also look into InitializingBean
and FactoryBean
.
For setting the active profile, one possibility is to do the following. Create an ApplicationContextInitializer
which sets the active profile by reading from a .properties
file. You won't be able to use @PropertySources
here because this isn't a bean.
Something like
public class ProfileContextInitializer implements
ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
PropertySource<Map<String, Object>> source = null;
try {
source = new ResourcePropertySource("spring.properties");
String profile = (String) source.getProperty("active.profile");
System.out.println(profile);
ConfigurableEnvironment env = applicationContext.getEnvironment();
env.setActiveProfiles(profile);
} catch (IOException e) {
e.printStackTrace();
}
}
}
You can register this in your deployment descriptor
<context-param>
<param-name>contextInitializerClasses</param-name>
<param-value>com.yourapp.ProfileContextInitializer</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
When the ContextLoaderListener
is created, it will pick up and instantiate your class and call its initialize
method. This is done before the WebApplicationContext
is refreshed.
You should probably just set a VM argument for the active profile and avoid all of this.