Keep track of all the classes that implement a particular interface? - java

It's difficult to explain what I really want. I have an interface which has a method getRuntimeInfo() which provides me all the runtime debug information for the variables of a class. I want to see the list of all the classes that implement this interface. I am using Java and Spring.
One way I can do this is to get all the beans from the Spring Context and check using the instanceof operator. But i wouldn't want to do that for obvious performance impacts. Do i have some other option?

What about this solution:
#Component
public class WithAllMyInterfaceImpls {
#Autowire
List<MyInterface> allBeansThatImplementTheMyInterface;
}
The List is only populated once (at start up) so it should not have a significant impact in the "normal" runtime performance.
Comment:
can you explain your code
You know Spring is a IOC Container. #Component tells Spring that it should create an instance of this class (a so called Spring Managed Bean). IOC means also that the Container is responsible to inject references to other instances (Spring Managed Beans). #Autowire (as well as #Resource and #Inject -- all do the same) is such an annotation that tells Spring that this field should be populated by Spring. Spring itself tries to figure out with what instances the field should be populates. A default technique that spring uses is by type this means that Spring inspect the type of the field, and search for matching beans. In your case it is a generic List - this is a bit special. In this case Spring populate the field with an list, where the elements are all beans that match the generic type.

How about the getBeansOfType method from ApplicationContext? It returns a Map of the beans implementing your interface?
http://static.springsource.org/spring/docs/1.2.x/api/org/springframework/beans/factory/ListableBeanFactory.html#getBeansOfType(java.lang.Class)

Related

Java Spring Boot how does constructor method dependency injection actually work

How does constructor method dependency injection work if I'm not even initializing the class anywhere or passing in arguments. Does Spring take care of this somewhere for me? Would really like to know more about this, if anyone wouldn't mind sharing/teaching me. How does this work on the heap? Would there be a reference to the class being constructed and the dependency so I would have two instances of different objects or just one? I found this answer How does constructor dependency injection work?, but it doesn't really answer my question in great detail.
Example:
#Controller
#RequestMapping
public class SampleController{
private final SomeRepository someRepository;
pulbic SampleController(SomeRepository someRepository) throws Exception{
// will someRepository ever be null?
if(someRepository == null)
throw new Exception("I told you it wouldn't work!");
this.someRepository = someRepository;
}
Answering your question: yes. Spring manages all the Beans on your behalf. You can declare a Bean in multiple ways:
XML (the old way);
Using #Bean (but in this case you would actually instantiate the Bean);
Using #Component, #Service, #Repository or #Controller (the later 3 are basically specializations of the first).
In your case, you have annotated SampleController with #Controller, so now Spring knows that it will need to provide this Bean for you by managing it in the Spring IoC container. However, so that Spring can create the Bean it will also understand that it needs another Bean to be available, in your case SomeRepository. If such a Bean already exists in Spring IoC Container then Spring provides it to your SampleController constructor. For this to work, SomeRepository must also be a Spring-managed Bean, and thus defined by one of the previous three ways.
It is worth mentioning that if for example you would have multiple SomeRepository Beans in your application (imagine an interface having multiple implementations, being each one a different Bean), you would need to "tell" Spring which one you want to be used in SampleController, otherwise you would get an error. There are multiple ways to do this:
Using #Qualifier annotations;
Using #Primary on one of the implementations to mark it as the "default" in case you don't explicitly "say" which one you want.
You can check examples in https://www.baeldung.com/spring-qualifier-annotation.
This is a very high-level description, but you can find some good articles online about this or even check the reference documentation.

Get application components without #Autowired

How would you extract something prior 2.5 version from .xml config? It bothers me because if #Autowired is removed from my arsenal I would not really know what to do.
Say I want to use some DAO implementation.
In service class I usually write:
#Autowired
someDaoInterface generalDao;
Then I typically call
generalDao.someInterfaceMethod(someParam param);
How would I extract implementation from config in Spring 2.0 to use this method?
Is it as dumb as just: new ApplicationContext(pathToXml) and then use .getBean or there is other way?
Why do I ask for taking bean out from configuration file?
Because in Spring MVC how can you perform your logic without getting beans out from the application context.
If you have #Controller handler then you need to make calls to the service classes' methods? So they should be somehow retrieved from the context and the only way so far is using #Autowired? Then I would also want to populate Service classes as I stated in previous example with DAO classes and they also need to be retrieved from the application context, so I would be able to write logic for service classes themself. How would people do it in the past?
I see the #Autowired as the only mean of taking something out, not because it is convenient to wire automatically - I am perfectly ok with XML.
You still have option to wire it explicitely via property or constructor parameter. (Anyway, autowired is not going to work if there is ambiguity in your container )
Of course, you can use application context and getBean() in your java code, but it violates DI pattern and makes all the spring stuff useless. Purpose of DI is to decouple your business loginc from implementation details - it's not business logic it's how and where it dependencies come from. Dependencies are just there.
By using ApplicationContext.getBean() you are breaking this pattern, and introduce dependency to:
spring itself
your configuration names
After you done this, you can as well drop use of DI and spring because you just voided all the advandages DI is providing to you. (BTW, #Autowired also introduces dependency to spring, and violates DI pattern, it also implies that there is only one instance available)
Also, answer is: in ideal case there shall be no reference to spring in your code at all.
No imports, no annotations - just interfaces of collaborating entities.

Instantiating spring bean objects

I've been playing with Spring and had a quick question...
I have a loop within class A which instantiates new objects of class B. To do this I've used the new operator however I cannot reference any Spring beans injected into instances of class B as I get a null pointer exception. I think I understand that this would be due to spring not managing these instances as beans and therefore not being able to manage the lifecycle however I was just wondering what the best way to go about creating multiple instances would be i.e. should I used appContext.getBean("beanA"); ?
First - are right with your assumptions. Using new means spring doesn't manage the object.
Solutions can be:
appContext.getBean("beanA"), where the bean is of scope "prototype". You obtain the appContext by injecting it, or by implementing ApplicationContextAware
using #Configurable and apsectJ weaving. That way even objects instantiated with new become managed by spring (the weaver plugs into the compiler or the vm)
using a lookup-method - it's the same as the first option (again requires prototype-scoped bean), but you get a method of your class that returns a new instance each time you call it.
Normally, however, you shouldn't need that. In the rare cases you do, I'd recommend the 3rd option.

Get access to all spring beans of a given type

I have a Spring application (Spring Batch not web application). In a test class, I want to grab access to all of my beans of a given type.
I understand that in Spring you should generally use IOC and let the container inject your beans. However in this case, I want to loop through a variable number of beans that extend a given class (org.springframework.batch.item.database.JdbcCursorItemReader), and do something (want it to be a unit/integration test that just connects it to the database and reads 1 row, so we can confirm at test time that all of the JdbcCursorItemReader in the system have valid SQL and row mappers).
Problem 1) I can only get beans one at a time. I can have my class implement BeanFactoryAware to get a reference to my beanfactory. Then I can do beanFactory.getBean("name"); to get access to a single bean. How do I instead get ALL beans? I can loop through and drop the ones that aren't the class I want.. but somehow I need a list of all beans the beanfactory knows about or something.
Problem 2) The bean I get back from the beanfactory is a proxy. If I try to cast and use my bean I get something like
java.lang.ClassCastException: $Proxy0 cannot be cast to org.springframework.batch.item.database.JdbcCursorItemReader
You can get around the first problem by using ApplicationContextAware instead of BeanFactoryAware. This will pass in the ApplicationContext, which has the getBeansOfType() method which lets you retrieve all beans that are of a given type.
The second problem is likely caused because something is creating AOP proxies around your JdbcCursorItemReader bean. These generated proxies will, by default, implement the same interfaces that JdbcCursorItemReader does (specifically, ItemReader and ItemStream). Your code should not try and cast to the class type (JdbcCursorItemReader), but to one of those interface types instead. It's usually possible to force the proxy to extend the proxied class directly, but without knowing anything about your setup, I can't help you with that.

What beans do you wire in a spring mvc app?

I am wiring my UserService type classes using spring's IOC.
But what about my User class?
I have a interface User, then a UserImpl class.
In my controller action's do I just do:
User u = new UserImpl();
Or would it sometimes make sense to use IOC for this also?
Sometimes I use a different constructor also when instantiating a class, based on some conditions. I guess your stuck in these situations?
It will not make sense to use dependency injection or IOC for your business objects like User because business objects are not the dependencies of the class they are the part of the class using them.
Spring IOC, by default, will create Singletons for you. Which means all user threads using your app will share that single instance of class. This is generally fine for Service type classes. If needed this singleton behavior can be changed to object per request (prototype), but this will cause you to change this setting for the users of the non-sigleton object as well.
Domain/business classes are state-full, it's easiest to create such objects once-per-request in order to avoid concurrency issues.

Categories

Resources