Is it possible to autowire bean name in Spring? - spring

Is it possible to autowire bean name in Spring using annotations instead of using BeanNameAware interface?

It is not possible out of the box, you can create own annotation #BeanNameInjected and register own BeanPostProcessor to deal with it.

You can annotate bean setter method with #Autowired.
public class SimpleMovieLister {
private MovieFinder movieFinder;
#Autowired
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// ...
}

Related

Can ApplicationContext.getBean() get the RequestScope bean correctly?

I need to use below RequestScope bean in some integration. Autowired doesn't work in the integration. Now I use ApplicationContext.getBean to get it.
#Component
#RequestScope
#Data
public class MyRequestBean{
public int random() {
return random;
}
}
#Component
public class SomeTask implements SomeIntegrationJavaDelegate {
//Autowired doesn't work
private MyRequestBean myRequestBean = ApplicationContext.getBean(MyRequestBean.class);
}
It works for singleton bean. Will it have any problem on RequestScope bean? How does it get correct RequestScope bean?
Try #Resource instead of #Autowired.

Spring: Qualifying different types with the same name

I have two classes that I want to autowire using spring
#Component
public class Restaurant {
#Autowired
#Qualifier("HighClass")
private CoffeeMaker coffeeMaker;
}
and:
public class CappuccinoMaker implements CoffeeMaker{
#Autowired
#Qualifier("HighClass")
int numOfSpoons;
}
Then injecting:
#Bean(name="HighClass")
#Scope("prototype")
public CoffeeMaker HighClassCoffeeMakerGenerator() {
return new CappuccinoMaker();
}
#Bean(name="HighClass")
public int getNumOfSpoons() {
return 3;
}
I'd like to qualify both the int and the CoffeeMaker with "HighClass". In Guice it is possible to annotate different types with the same annotation and inject them correctly.
It seems like in spring this is not allowed. When I try injecting the fields I get an error that the required bean was not found. Did I miss anything?
Bean name in Spring is unique. Use #Profile in order to pick a bean from several competing variants.

POJO Injection in Spring similar to CDI

I have some java objects coming from external library which I need to inject in my spring project. Problem is the classes from library is not aware of any spring api's
If I inject the beans from library to Service using #Autowired I am getting org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type
Following is my service class
#Path("/test")
public class TestService {
#Autowired
SomeOtherClass service;
#GET
public Response get(){
return Response.ok(service.someMethod()).build();
}
}
and following is my class from library which is not aware of spring
public class SomeOtherClass {
public String someMethod(){
return "Data from library";
}
}
When I invoke my service I get exception as
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.SomeOtherClass' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Is there are way in spring to inject a plain Java Object similar to that of injection in **CDI**?
There is one option to define applicationcontext.xml and define SomeOtherClass in xml and use getBean, but I don't want to do that. Is there any other option?
Note:
Following options cannot be considered because I have100's of classes coming from library
Cannot use applicationcontext.xml
Cannot #Configuration #Bean to produce beans.
You could use the #Configuration and #Bean annotations as follows -
Create a new class:
#Configuration
public class AppConfig {
#Bean
SomeOtherClass someOtherClassBean(){ return new SomeOtherClass();}
}
Now the auto wiring shall work.
What it does, is actually creating a bean and letting Spring know about it.
Maybe try adding the beans programatically to the IoC container:
Add Bean Programmatically to Spring Web App Context
You need to find all the classes you want to instantiate and use one of the methods in the linked question.
You can use reflection to add Bean definitions programatically.
#Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
Reflections ref = new Reflections(new ConfigurationBuilder()
.setScanners(new SubTypesScanner(false /* don't exclude Object.class */), new ResourcesScanner())
.setUrls(ClasspathHelper.forPackage(PACKAGE_NAME))
.filterInputsBy(new FilterBuilder().include(FilterBuilder.prefix(PACKAGE_NAME))));
ref.getSubTypesOf(Object.class).stream()
.forEach(clazz -> {
logger.info("Defining pojo bean: {} -> {}", Introspector.decapitalize(clazz.getSimpleName()), clazz.getCanonicalName());
registry.registerBeanDefinition(Introspector.decapitalize(clazz.getSimpleName()),
BeanDefinitionBuilder.genericBeanDefinition(clazz).getBeanDefinition());
});
}
Subsequently, these beans can be #Autowired elsewhere. See Gist: https://gist.github.com/ftahmed/a7dcdbadb8bb7dba31ade463746afd04

Spring Autowired annotation with service implementation

I have few doubts in the scenario below.
Having one interface and two implementation classes:
Interface:
interface ServiceInt
{
public void save();
}
First implementation class:
Public class ServiceIntImpOne implements ServiceInt
{
public void save()
{
// I am first service implementation
}
}
Second implementation class:
Public class ServiceIntImpTwo implements ServiceInt
{
public void save()
{
// I am Second service implementation
}
}
Main class calling the save method of an implementation class:
Public class controller
{
#Autowired ServiceInt;
public void save()
{
ServiceInt.save()
}
}
My Questions:
ServiceInt.save() – which save method of service class implementation will it invoke?
How we can use the save method implementation of the ServiceIntImpTwo class?
How does autowired work?
ServiceInt.save() – which save method of service class implementation
will it invoke?
If you have two beans of the same type (beans defined via annotations or via xml) when you autowire that beans it will fail (throw exception), because Spring don't know what bean to inject.
caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException:
No unique bean of type [ServiceInt] is defined:
How we can use the save method implementation of the ServiceIntImpTwo
class?
If you defined your bean in a xml file, then you can use the id property
<bean id="beanTwo" class="ServiceIntImpTwo" />
then you can autowire using Qualifier annotation
#Autowired
#Qualifier("beanTwo")
ServiceInt myServiceTwo;
if you are using annotations instead.
#Component
Class ServiceIntImpTwo impl...{}
Then you can autowire
#Autowired
#Qualifier("serviceIntImpTwo ")
ServiceInt myServiceTwo;
How does autowired work?
This you can read it on Internet.
http://memorynotfound.com/handling-multiple-autowire-dependencies-with-spring-qualifier/
https://www.mkyong.com/spring/spring-autowiring-qualifier-example/
https://www.tutorialspoint.com/spring/spring_qualifier_annotation.htm
If you have two implementation to one interface you will need to provide spring hint which one to use:
you can use #Qaulifier annotation
you can use #Profile and choose the active profile.

Injecting a bean inside another bean and use it in the constructor?

I have a bean that looks like this:
#Component
#Scope("session")
public class AlarmChartSettingsBean implements Serializable {
...
Inside this bean i inject another bean like this:
#Inject
private SessionInfoBean sessionInfoBean;
Then i call the injected bean inside the constructor of the first bean like this:
public AlarmChartSettingsBean() {
String atcaIp = sessionInfoBean.getNwConfigBean().getAtcaIP();
}
The problem is that the injected bean is null. So the question is when is that bean injected? Can i use it inside the constructor or i should use it after the bean has been constructed?
The constructor of a Spring bean is called before Spring has any chance to autowire any fields. This explains why sessionInfoBean is null inside the constructor.
If you want to initialize a Spring bean, you can:
annotate a method with #PostConstruct:
#PostConstruct
public void init() {
String atcaIp = sessionInfoBean.getNwConfigBean().getAtcaIP();
}
implement InitializingBean and write the initialization code inside the afterPropertiesSet method:
public class AlarmChartSettingsBean implements Serializable, InitializingBean {
#Override
void afterPropertiesSet() {
String atcaIp = sessionInfoBean.getNwConfigBean().getAtcaIP();
}
}
The #Inject on a Field will autowire after the constructor has been called.
Note: In some Spring-Apps the #Inject may not work, use #Autowire instead.

Resources