Run time polymorphism using Spring IOC - spring

i have this specific question regarding spring IOC . I want to achieve runtime polymorphism using spring .
I am able to achieve the same using if else , however i would like a know a proper spring-way of doing it .
Requirement :
I have interface MyInterface .
ImplA & ImplB implements MyInterface .
I have a service which sends "A" or "B" . Based on the request-param i want to inject ImplA or ImplB in my controller .
Please suggest what will be the best way to implement the same in spring using dependency injection

If you use spring annotation base configuration try it:
#Bean(name = "aImpl")
public MyInterface a() {
return new AImpl();
}
#Bean(name = "bImpl")
public MyInterface b() {
return new BImpl();
}
To get the properly instance of interface clarify bean name with #Qualifier
#Autowired
#Qualifier("a")
MyInterface aImpl;
#Autowired
#Qualifier("b")
MyInterface bImpl;

There are many ways to achieve this. Couple of ideas from my point of view:
Use Factory pattern to return the bean you want based on the param value.
Put both the beans in map and using param values as key. When you need the bean get it from the map.
Let me know if you need more information.

You can use applicationContext.getBean("beanName") inside your controller method. Here is an example program. You can get the right impl this way based on your condition.

Related

Get dependency type via Spring container at runtime

Suppose I have following code to define someBean:
#Bean
public SomeInterface someBean() {
return new SomeInterfaceImpl();
}
I want to get the interface type, namelySomeInterface, of this bean only from spring container at runtime. I tried the following code, but I found the def object knows nothing about SomeInterface.
ApplicationContext container = new AnnotationConfigApplicationContext...
BeanDefinition def = container.getBeanDefinition("someBean");
Is it possible to get it only from the container object? If possible, please tell me how. Thanks in advance.

Spring return dynamic instance based of String value

Java Spring question:
I have a interface MyInterface with one method
void exec (String str);
I have many implementation of MyInterface, say Oneimpl, anotherimpl yetanotherimpl...and so on and can keep adding new implementations.
how do I obtain an instance of a specific implementation using just the name of the implementing class passed as a STRING value , say "someRandomImpl"
The code should be dynamic and can provide a instance of new implementations without code change.
implements ApplicationContextAware
it will autowired ApplicationContext object
use the object like
context.getBean(beanName)
then you get the bean

How to create custom abstract repository like PagingAndSortingRepository, etc?

For example in my persistence:
public interface SomePersistence extends JpaRepository<SomeClass, String> {};
I can write method like:
#Query("some query")
List<SomeClass> getAllWithSomeParam();
and spring knows to use SimpleJpaRepository class - implementation of JpaRepository.
When i write:
#Query("some query")
Page<SomeClass> getAllWithSomeParam(Pageable page);
spring knows to use implementation of PagingAndSortingRepository.
But now i want to add my own returned type - Cursor<T>
It`s mean i want write:
#Query("some query")
Cursor<SomeClass> anyMethodName();
Then i want to give spring my own repository CursorRepository with its personal CursorRepositoryImpl when i have only one method Cursor<T> findAll()
Can i realize it?

Spring constructor injection

Is it possible to construct an object manually and let some other arguments be injected by Spring?
e.g.
class A
#Autowired
private SomeDao dao;
A(String x, String y) {}
Your example is using field injection, not constructor injection.
The best way is generally to use JavaConfig. Your #Bean methods can take parameters (which Spring will autowire), which you can combine with your other options when you call new.
Maybe org.springframework.web.context.support.SpringBeanAutowiringSupport class it's what you are looking for, try to invoke:
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
You can use autowireBean from the AutowireCapableBeanFactory. Given your applicationContext, you call getAutowireCapableBeanFactory() and then autowire your instance:
applicationContext.getAutowireCapableBeanFactory().autowireBean( new A("x", "y" ) );

Marker interface with Multiple implementations...!

I have a question regarding how to implement Marker interface through spring. I need to point my marker interface to its implemented classes. Itself marker interface dont have any of function declaration.
interface A {
/* No Method declaration */
}
#Component("c")
Class B implement A {
void function1(){ .. }
void function2(){ .. }
}
#Component("c")
Class C implement A {
void function3(){ .. }
void function4(){ .. }
}
Now Some where in my business Logic, i would like to use #Autowire though my interface to point any of one implementation.
#Autowired
#Qualifier("b")
A aB;
#Autowired
#Qualifier("c")
A aC;
It dont work. Will you please help to implement in correct way…! I was expecting thorugh reflection it should give me the list of method available in the implemented classes but it dont.
Added More Details
The only thing i would like to do is, I would like to reply IResponse to my business methods, instead of different tyoe. Its ok for me if i would have to #Authowired direct to implementation like
#Autowired
B aB;
but i thought if there is some way my IDE and Spring do some logic and when i #Autowired my interface towards implementation then it should be able to pick my Implementation class and should show me the business methods. Its not magic, when i am using qualified. I just want from spring to show me business methods through reflection.
What is the point of injecting A exactly? You probably expect Spring to do some kind of "magic" when it injects the dependency. It does not. I will simply inject the bean that you have required if it can inject it. In your case, the Qualifer value gives a hint as to which bean instance spring injects.
Except the typo (it's #Autowired, not #Autowire), this code should indeed inject B and C. But as you declared them as being A in your code you'll get a simple java.lang.Object basically. That's just a fundamental principle of Java that is strongly typed language.

Resources