I have a class GList which implements the interface IQList.
I have a class Qurious in which I need a Provider to provide prototypes of GList. (Besides annotating GList scope as prototype).
However, I do not want Qurious to be aware of the existence of GList. Therefore, in Qurious, I have a declaration
Provider<IQList> qlistProvider.
What do I have to do with either GList or applicationContext, so that Spring will instantiate GList to satisfy
Provider<IQList>
?
I am trying to avoid defining a factory.
If I understood you correctly:
Instantiatin Spring bean of type Provider in spring configuration
and annotating your Provider<IQList> qlistProvider. as #Autowired should be enough.
Or do you want Spring framework to guess that you will need a particular type of object instance and do it for you? I don't think that it can
Related
I have 2 scenarios where I would like to understand/confirm the usage of #Component:
Extending concrete class:
I have a concrete super class A and its sub-class Aa in my web application. I have annotated with Aa with #Component(value="aa") and #Scope(value=WebApplicationContext.SCOPE_SESSION). Also, I have annotated A class with #Component(value="a") and #Scope(value=WebApplicationContext.SCOPE_SESSION).
My question -> I am only doing applicationContext.getBean("aa"). I can skip the annotations in A class (please correct me if I am wrong), but I don't know why and how? My understanding has been that if a class is not annotated with #Component or defined in bean configuration file then Spring doesn't handle its instance management.
Abstract concrete class:
Same scenario and question as above just that in this case super class is an abstract class.
You have to register the beans via beans in a config or via component annotations (Repo or controller or service). If not the bean is not contained in your application context container.
#Component add a bean in the Spring registry. Then, you can retrieve this bean later.
If you don't use the bean, there is no need to add it to the bean registry. (so just remove #Component(value="a") and #Scope(value=WebApplicationContext.SCOPE_SESSION) )
On your use case, you set a scope to SESSION. It means that every time you create a session, Spring will instantiate your class (A / Aa) and put it on the session. As it is an instance of the class you don't need the super class instance (A) to be able to create the Aa instance.
With A beeing abstract, it is exactly the same thing, except if you try to scan it for Spring to pick it, Spring will throws an error saying A cannot be instantiated.
I have a class that would otherwise be a very generic POJO but I would like to inject a dependency in it because I would like to avoid passing that dependency as a (constructor) parameter:
//no managed context annotation because it's a simple POJO
public class QueuedBatch {
//however, I would like to inject the context managed bean below
#Autowired
AsyncActionQueue asyncActionQueue;
Currently, no exception is thrown at deploy time but asyncActionQueue is null at runtime so I get a NullPointer when I hit the POJO.
How can I annotate my POJO to add it to the Spring managed context so that I can inject dependencies into it? AsyncActionQueue is a singleton and I would rather not be passing it to QueuedBatch as a (constructor) parameter.
This post is similar, except that I want to add my POJO into the managed context.
As the comments suggested you have 2 ways of dealing with this
Pass the AsyncActionQueue as a parameter in the constructor of QueuedBatch. This doesnt require Spring to know anything about QueuedBatch, but enforces the dependency to be provided when an instance of QueuedBatch is created.
Annotate the QueuedBatch class with #Component. And ensure that the package which contains QueuedBatch is included in the component scan when initializing the spring context. In this way, it becomes a spring managed bean allowing AsyncActionQueue to be autowired into it. You may change the scope of QueuedBatch component based on your requirement.
I have created a few interfaces extending CrudRepository. I'd like to use them into a generic class that is not a bean. What I do currently is to inject them using #Autowired inside my RestController and then pass them down as method arguments to this generic class I'm talking about. Is there a better way to achieve this?
One approach is to make your unmanaged class extending SpringBeanAutowiringSupport and use #Autowired properties. If your application has a Spring web application context, it can then try to get the context from the current thread and resolve the #Autowired properties for you.
In my ApplicationContext I have several Beans being created the same style. So I have a lot of dublicated code writing a FactoryBean for each of this beans. Those beans have a common ground, implementing all one special interface.
I would like to move all that bean creation to one factory. That one would have to provide a methode like this
<T extends CommonInterface> T createInstance(Class<T> clazz);
There I could implement all the instantiation necessary to create one of my special beans.
My implementation would be called by spring for
#Autowired
private MyCommonInterfaceImplementation impl;
in that way
createInstance(MyCommonInterfaceImplementation.class)
So far I looked at BeanFactory and FactoryBean, both seem not to be I'm searching for.
Any suggestions?
why not use #bean
#Bean
public MyCommonInterfaceImplementation getMyCommonInterfaceImplementation(){
return MyBeanFactory.createInstance(MyCommonInterfaceImplementation.class);
}
//should autowire here
#Autowired
private MyCommonInterfaceImplementation impl;
Basically you need the #Bean annotation on a "factory" only if you need some special handling during the creation of a bean.
If everything can be #Autowired, either by setters, fields, or one constructor, and nothing else needs to be done on a bean during initialization, you can simply declare the annotation #Component on each implementation of your interface. This works as long as you have component scanning active inside your application. The result will be that for each component spring will create a bean which you can use.
I'm writing this on a mobile so showing code is not the best. Just follow some tutorial on #ComponentScan, or if you need, let me know and I can augment this answer with an example.
As of Spring 4.3 you no longer have to annotate your bean classes and you can let them be instantiated via a componentscan.
#Configuration
#ComponentScan(
value = "some.package.path",
includeFilters = {
#Filter(type = ASSIGNABLE_TYPE, value = {
MyClass1.class,
MyClass2.class,
MyClass3.class
})
})
This actually creates beans for the three classes listed there. The example should work without filters as well (everything in the package becomes a bean). This works as long as the classes have a single constructor that can be used for autowiring. I don't think it is possible to filter for all implementations of a particular interface and then register a bean.
To do that, you might do something with a ContextListener and e.g. use reflection to find out what classes to instantiate and then use context.autowire(..) to inject any dependencies from your context. A bit hacky but it might work.
#Override
public void onApplicationEvent(ContextRefreshedEvent event) {
ApplicationContext context = event.getApplicationContext();
MyClass bean
= context
.getAutowireCapableBeanFactory()
.autowire(MyClass.class, Autowire.BY_NAME.value(), true);
...
}
That still leaves the problem of how to get the bean registered in the context of course.
You might also be able to adapt the answer to this SO question on how to add beans programmatically.
Finally the best approach I've found is using a ConfigurationClassPostProcessor. As example I've used https://github.com/rinoto/spring-auto-mock
But, since it is quite complicated and "too much magic" to create beans from nothing, we decided to explicitly create those beans via #Bean.
Thanks for your answers.
Given having next classes:
XRepository with declared a constructor with 1 argument (simple one,
not autowired), it has some autowired fields.
XService that uses XRepository as autowired.
XProcessor uses XService as autowired.
So I have to init XProcessor on runtime for specific value that will be used in XRepository constructor. On different calls I will have different arguments, so the injection should be on runtime.
Any idea how to achieve that using code configuration or annotations?
Remember that Spring needs to inject all the constructor parameters of Spring managed beans.
I believe you have two options:
Parse your URL info in controller and pass it through parameters down to persistence layer. This would be my preferred mechanism. You can create special DTO for passing various information down and keep your method signatures concise.
Your situation can alos be solved with request scope bean. You will
create one bean like this:
#Component
#Scope("request")
public class {
private String urlPart;
}
And you would autowire this component into XProcessor and
XRepository. Each request to your application will create new
instance of XRequestContext and you will parse your info in
XProcessor and store it into XRequestContext.
In XRepository you will use instance of XRequestContext to
retrieve information you stored in XProcessor.
You can read about request scope in Spring docs. It is like
ThreadLocal per request thread.