I'm using java config with #ComponentScanin order to initialize my beans
and #EnableAspectJAutoProxy(proxyTargetClass=true)to use cglib proxies.
In this project we have a lots of generated services autowired between them using #Autowired. It works pretty well.
But, for some of these services I've added #Async (I've also added #EnableAsync(proxyTargetClass = true)on my #Configurationclass).
After that, I'm getting:
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'ConversationUserLocalService': Bean with name 'ConversationUserLocalService' has been injected into other beans [ConversationUserHistoryLocalService] i
n its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'a
llowEagerInit' flag turned off, for example.
I guess this is because Spring is injecting the service with #Asyncmethod BEFORE AOP creates the proxy.
Could this be the problem?
How I should fix it?
In order to try to clarify my problem, let's say I have:
#Service A, B & C;
A has autowired B & C, B has autowired A & C, C has autowired A & B;
C has a method marked as #Async.
When Spring initialize applicationContext, it tries to initialize A, but needs B & C, so it initializes them. But after all, AOP tries to make a proxy of C (because #Async) and then it detects that autowired C into B and A is not the same as proxy of C so it fails.
I hope this can explain a little more what is happening.
Finally I sorted it out using #Lazyon services (with methods annotated with #Async), and also, where they were autowired.
This way I guess Spring only initialize and autowires those services when they're required instead of on application context initialization.
I have same issue and I solved this issue:
I identified which #Autowired property is reason for circular dependency.
Eg:
#Autowired
private TestService testService;
(Tips to identified just try to comment and find out which property is reason to break the application)
Once identified just use #Lazy on top of this #Autowired variable.
Eg :
#Lazy
#Autowired
private TestService testService;
And Application worked smoothly.
AsyncConfigurer configuration classes get initialized early in the application context bootstrap. If you need any dependencies on other beans there, make sure to declare them #Lazy as far as possible in order to let them go through other post-processors as well.
Reference JavaDoc: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/scheduling/annotation/EnableAsync.html
I managed to fix a similar issue by adding #Qualifier together with #Autowire, for example:
#Autowired
#Qualifier("publisher")
private Publisher publisher;
Related
From the official documentation:
When registered by type, any existing single bean of a matching type (including subclasses) in the context will be replaced by the mock
What if the service under test is autowired in the constructor, though? E.g. in Kotlin (I suppose #MockkBean and #MockBean work the same regarding DI):
#RunWith(SpringRunner.class)
class ExampleTests #Autowired constructor(val userOfService: UserOfService) {
#MockkBean
private lateinit var service: ExampleService
...
}
I would expect this example to fail because in order to instantiate ExampleTests Spring has to first obtain a proper instance of UserOfService. That shouldn't be possible at that time, though, because there's no bean of type ExampleService in the application context yet.
Contrary to my expectation, this works. How is it possible?
Because you miss the other part from the documentation :
In either case, if no existing bean is defined a new one will be
added.
So #MockBean will also instantiate a bean automatically if that bean is not found in the spring context.
The sequence of actions are mainly as follows :
Start up the spring context which create all the spring BeanDefinition only that are registered in the spring context.
Process #MockBean which will replace the BeanDefinition in (1) or create a new BeanDefinition
Actually instantiate all the beans based on these BeanDefinition. It will handle which bean to be actually instantiated first and later.
Create a test instance (i.e ExampleTests) to execute its test methods. If any beans required to be auto-wired into the test instance are not created , it will fail.
So as long as you define UserOfService bean , ExampleTests can be instantiated as you are now using #MockBean on the ExampleService which means it must exist no matter you define it or not in the spring context for the test.
I am new to Spring so my understanding of it is very superficial, nevertheless, suppose we are looking at the following example:
class serviceImpl implements service{
#Autowired
private Mapper mapper;
public void executeService(){
mapper.executeSerice();
}
}
So, I am trying to build some service, which calls mapper from the persistence level. Mapper is an abstract class. So from my understanding, #Autowired will automatically injects one implementation of Mapper here.
Then my question is:
What if there are multiple implementations of Mapper? After some search, it seems that in this case one needs to use #Qualifier to designate which implementation we want to use.
Suppose we are using the implementation powerfulMapper, then we will need to use #Qualifier('powerfulMapper').
Then how is this different from just instantiating Mapper powerfulMapper here?
If you have only one Mapper , you only need #Autowired to inject. If there are more than one Mapper implementation registered as Spring bean , you have to use #Qualifier or #Resource to tell Spring which implementation you want to inject. See this for more details.
Then how is this different from just instantiating Mapper
powerfulMapper here?
The difference is that if a class is a Spring bean , we can apply some Spring feature on it such as :
Apply some AOP magic on it such as #Async , #Transactional , #PreAuthorize etc.
Think about the case that if a class has a lot of dependencies which in turn has a lot of dependencies, creating an instance of this class configuring with the whole dependency graph is not an enjoyable thing to do . Not to mention different dependency can has different requirements (e.g. one may needed to be instantiated as a singleton and will be shared to be used by different class while other may need to be in the prototype scope which different classes need a separate instance etc.)
Using #Autowired and let spring to configure such dependency graph is more easier than do it manually.
On the other hands , if the Mapper has very simple dependencies , only used internally inside ServiceImpl and you don't need any benefit provided by spring on it , you can simply instantiate it without declaring it as spring bean.
Dependency Injection (DI) is so that you avoid having a complicated tree of dependencies.
Imagen having a tree like structure where A instantiates class B and class B instantiates class C, then A instantiates D and D instantiates E.
A --> B ---> C
\
\--> D ---> E
This is all fine fine, until class E needs class C.
Then we need to re arrange everything and instantiate C higher up and pass it through class B and D down to both sides.
This is where DI comes into play.
We instead decide that A instantiates all classes
A --> B
--> C
--> D
--> E
So A is the owner of all classes, and he can then pass in any class to any class to meet whatever demand any class has.
This is what the Spring context does with the help of the #Autowire annotation. You declare for spring what class you want to be passed in the instantiated classes. Then Spring during startup, will instantiate all classes and then figure out what class should be fitted where (this is massive simplification). All classes will per default be instantiated as singletons (but this can be customised).
When spring instantiates you class it is called a spring managed bean. Spring manages the lifecycle of it. Not you, because you are not using new, the framework is.
During this process Spring does a number of checks and also instantiates in a specific order, configuration classes first, then #Bean annotated classes, and lastly #Component, #Service etc (overly simplifying this here), it will scan for what classes that should be instantiated, it will decide upon an order in which should be instantiated first, then which classes should be #Autowired into which classes. There are a number of help annotations that will assist Spring during this phase.
#Qualifier is one, you basically name a class, then you can tell spring where you want it #Autowired.
It's very useful if you have two singletons configured differently but they have the same name.
As you said, if you want different implementations you need to use #Qualifier("powerfulMapper") etc.
Lets suppose you have two different implementations one use #Qualifier("powerfulMapper") and the other is #Qualifier("notAPowerfulMapper").
Then while you autowire you also need to specify which one you need to inject like
#Autowired
#Qualifier("powerfulMapper")
private Mapper mapper;
I know and understand constructor based injection. But, the autowiring modes confuse me.
1) I have read that default mode for autowiring is 'no autowiring' i.e. We have to manually set the properties in xml file. But, isn't xml based configuration a type of autowiring? How can it be considered 'No autowiring'?
2) Other modes for autowiring are i) byName ii) byType iii)constructor iv) auto-detect. Am i correct to assume the following:
a) When using xml configuration based autowiring, the default mode is 'byName'(i.e. I have to keep the name of property reference the same as the name of the bean which is being used as a property.)
b) When using Annotations, default mode is 'byType'( Regardless of the place the #Autowired keyword is placed i.e on the setter, on the constructor or on the property, it will search the type of the property being autowried)
3) What is the difference between constructor based injection and 'constructor' mode of autowiring?(I have read that constructor mode means it applies byType mode on all the constructor arguments, but how is it different from placing #Autowired keyword on the constructor)
4) I know that to enable autowired mode byName in annotations, in the bean definition in the xml file, I have to use " autowire = 'byName' ". But, suppose I am using Annotations only config( using #Component, and no bean definitions in the xml ), and I want to use byName autowire mode, then what is the way of doing that?
I think you are a bit confused. First, you need to understand dependency injection (see here). There is ton of info about DI but in short, it means some third party (e.g spring IOC) passes the dependencies to the objects rather than the objects to create/obtain the references themselves. This could happen either through constructor or setter. For instance, consider constructor DI
class B{
}
class A{
private B b;
public A(B b){
this.b = b;
}
}
Some third party will inject an instance of class B into A rather class A create a reference to B itself. Very often you would use an interface so class A wouldn't even know what object will be injected into it.
Now in Spring there are different ways to configure these associations between the objects (the example above). You can either use XML, Java Config or Autowiring. They are independent but do the same stuff.
In both XML and JAVA config you need to configure the dependencies explicitly - either in xml file or having a #Configuration class for the JAVA Config and annotating the beans with #Bean. The autowiring is different. There you create simple POJOs which you annotate with #Component, #Controller, #Service or #Repository. They will be automatically registered as beans via component scanning. With autowiring you don't need to explicitly configure the dependencies in XML file or JAVA Config class. You can do it in code directly. For instance, if we have to compare java config vs autowiring using the previous example
Java Config (explicit config in a config class)
#Bean
public A getA(){
return new A(new B());
}
Autowiring (implicit - done in code)
#Component
class B{
}
#Component
class A{
private B b;
#Autowired
public A(B b){
this.b = b;
}
}
In the latter we autowire class B into class A (they both will be registered as beans due to #Component annotation) without having explicitly defined this association in an xml file or java config class. I hope it makes sense.
If you have to specify the bean names in the xml, its not happening automatically, hence its not autowiring.
With autowiring spring will figure out what bean to inject even though it may not be explicitly written.
When using xml configuration based autowiring, the default mode is 'byName'
When using Annotations, the ordering that happens depends on the annotation used as there are a few that can be used. #Autowire #Resource #Inject.
When using #Component, the default wiring is of type. The method below will resolve on any autowiring needs for a Service object.
#Bean
public Service getMyService(){
return new Service();
}
If there are multiple #Bean methods that return a Service you will get an error.
If you wanted to do wire via name while using #Component you would add the #Qualifier("nameToUse") annotation to the variable. It would find an #Bean annotated method called getNameToUse().
#Autowired
#Qualifier("nameToUse")
private Service myService;
I have a bean with autowired beans.
So something like:
class A
{
#Autowired
B b;
#Autowired
C c;
void function()
{
// here I would like to do something when I an sure the wiring has been done
// being sure that I won't wait forever
...
Something has to exist, but I can't find it.
Thanks for your help!
You can annotate your 'function' method with #PostConstruct and specify <context:annotation-config/> in your spring config XML. Then, function will only be invoked after autowiring, so you could check in function whether your beans have been injected successfully.
A classic way to achieve this is to implement InitializingBean:
Interface to be implemented by beans that need to react once all their properties have been set by a BeanFactory: for example, to perform custom initialization, or merely to check that all mandatory properties have been set.
An alternative to implementing InitializingBean is specifying a custom init-method, for example in an XML bean definition. For a list of all bean lifecycle methods, see the BeanFactory javadocs.
I also suggest reading other answers:
How to call a method after bean initialization is complete?
What is the difference between BeanPostProcessor and init/destroy method in Spring?
If you are using default scope for beans that is singleton, then autowiring will always be done at the application startup only. If wiring for any field fails, then spring container will throw an exception and the application will not start properly. So, if the control of code is in your method , it means wiring has already been done.
I wanted to understand how exactly the #Autowired annotation works.
import com.test.WorkFlowDAO;
public class ServiceCentralBOImpl implements IServiceCentralBO
{
/**
* Logger for logging functionality.
*/
private static final Log log = LogFactory.getLog(ServiceCentralBOImpl.class);
#Autowired
private WorkFlowDAO workFlowDAO;
.
.
.
}
and the bean is declared in my Spring applicationContext.xml file:
<bean id="workflowDAO" class="com.test.WorkFlowDAO">
</bean>
Upon closer inspection you can see the two IDs in the Java class and the context XML file are different.
workFlowDAO and
workflowDAO
[The letter 'f' is different in the two IDs]
Since my application runs just fine even with this configuration; I wanted to know,
how does #Autowired annotation work so that it does not complain when the bean IDs do not match exactly.
In case of simple bean usage; Spring would have complained of mismatching bean names.
I am running a J2EE application with Spring 3.0.5 on Websphere App Server 7.0
Let me know if any more information is required.
#Autowired matches the beans by type. The ID is not considered.
If you declare another bean of the same type in your XML configuration, Spring would complain about not being able to determine the correct bean.
If you want to use IDs together with #Autowired you can do so by utilizing #Qualifier although #Resource is recommended in this case.
Find some more info on that topic here.
Completely agree with the first comment.
If you want your beans to be autowired by name, you may consider using #Qualifier("givenName").
See for all details:
http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html