Spring drawbacks of Lazy annotation - spring

I want to resolve a circular dependency with it.
I am aware that there is a drawback of this annotation namely in case of a bean misconfiguration the error will come to the surface only at invocation time:
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Lazy.html
"Please note that such a lazy-resolution proxy will always be
injected; if the target dependency does not exist, you will only be
able to find out through an exception on invocation. As a consequence,
such an injection point results in unintuitive behavior for optional
dependencies."
My question is this really a drawback in any sense if I already use the given bean as non-lazy singleton at other parts of application? Which basically proves that the bean itself can be created.
example:
#Component
class A {
#Autowired
private B b;
}
#Component
class B {
#Autowired
#Lazy
private A a;
}
#Component
class C {
#Autowired
private A a; <- this is the evidence that the bean can be created so it wont fail when injecting it into classB when invoked
}

As long as your configuration is correct, it should work. In some cases, you need circular dependencies and this is the best way that I've found to implement.
Constructor injection is better but won't always work.
Alternatively, you can inject the BeanFactory and fetch in a #PostConstruct or afterPropertiesSet() method, but using #Lazy property injection seems cleaner.

Related

Difference between #Autowired and #Required with setter injection in Spring

I know a lot had been written about #Autowired and #Required annotations.
But I have a very basic question as below -
What is the difference between the below two mechanism of setter injection.
I haven't yet got a complete satisafactory answer for this.
The reason is :
1)#Autowired without any extra information like - #Autowired(required=false) is same as #Required
2)What are we gaining from #Required additionally ?
3)Why #Required is recommend over #Autowired on setter injection ?
class MyClass {
private MyService myService;
#Autowired
public void setMyService(MyService val) {
this.myService = val;
}
}
class MyClass {
private MyService myService;
#Required
public void setMyService(MyService val) {
this.myService = val;
}
}
#Autowired is not the same as #Required.
The #Required-Annotation is specialized for telling Spring that this property has to be injected by the information given in the XML-configuration-file (eager) and not through annotations. And that doesn't matter when you use the #Autowire-Annotation.
The #Autowire-Annotation (as in your code-example), tells the ApplicationContext (a.k.a the Spring-IoC-Containter) to inject the desired dependency. (No matter how, if its by using annotations or the XML-File of the ApplicationContext).
The #Required-Annotation, tells the ApplicationContext that this property has to be mentioned in the XML-file (The XML-File of the ApplicationContext), but the Annotation on its own doesn't tell to inject the dependency. So it is used to check if it is in the XML-configuration file, but not to inject a dependency. The injection is done because the property is mentioned in the XML-file.
So in the end it tells that the injection has to be done because of a configuration in the XML-File. But again: The annotation doesn't tell that the dependency has to be injected, but that it has to be mentioned in the XML-File - which then lets the dependency be injected.
With mentioning the property in a XML-File I mean such a configuration for instance:
<bean id="MyClass" class="com.myclasses.common.MyClass">
<property name="someProperty" value="ValueThatHasToBeInjected" />
</bean>
So why should I use it over the #Autowired-Annotation?
You should use it when the dependency has to be injected due to the informatoin given in the XML-configuration file.
Can you give me an example?
Well, there is already a very good example on this website. where this is also explained.
1) You can think of #Required as a check that the property has been eagerly initialised. In other words it requires that it's been injected via configuration (xml or annotation). If annotation is used then you'll see it alongside #Autowired. If the Bean injected does not exist the application fails to startup with a runtime exception.
2) Nothing more nothing less. #Required is very specific in what it's meant to be: a) only applicable on methods, b) requires the bean or else application runtime error on startup. Again, you need dependency injection either via annotation or xml.
3) Most likely you want to know at startup if a Bean is failed to be injected and for that reason you can have #Required along with #Autowired for expressiveness. Functionality-wise you don't need it if you have #Autowired.
Extra notes:
#Autowired has more functionality on the other side of the coin that is - when you want to achieve laziness. So on a setter method:
as you mentioned #Autowired(required = false)
Can also be paired with #Lazy
you can have #Autowired (without required = false) on a setter method whose param is Java 8's Optional achieving the same effect.

Spring Boot Constructor based Dependency Injection

I'm a beginner with Spring Boot and Dependency Injection and I can't get my head around Constructor based Dependency Injection in Spring Boot. I have class called ParameterDate that look like this:
public class ParameterDate {
private Date parameterDateUnadjusted;
private Date parameterDateAdjusted;
private Date parameterDateAdded;
private Date parameterDateChanged;
}
I have another class where I want to use ParameterDate. Normally I would do Field based Injection with
#Autowired
ParameterDate parameterDate;
And where ever needed I just use parameterDate.
How would I do this with Constructor based Injection?
public MyClazzRequiringParameterDate(ParameterDate parameterDate){
this.parameterDate = parameterDate;
}
Since Boot 1.4 #Autowired has been optional on constructors if you have one constructor Spring will try to autowire it. You can just tag the constructor with #Autowired if you want to be explicit about it.
Generally speaking you should favour Constructor > Setter > Field injection. Injecting directly to the field misses the point of DI, it also means your tests are reliant on Spring to inject dependencies into rather than just being able to pass mocks or stubs directly to it. Jurgan Holler has stated that he would remove field injection if at all possible.
#Component
public class ParameterDate {
private Date parameterDate;
#Autowired
public ParameterDate(Date parameterDate){
this.parameterDate = parameterDate;
}
}
Above is an example of constructor injection.
Note that you can use #Autowired annotation also on property's setter method, and since there is no difference between setter method (except of course it's purpose, logic it contains) and any other method, you can use #Autowired on just about any method of the class.
Since autowiring and component scanning go hand in hand, you should mark your class with #Component annotation. This tells Spring that a bean should be created for this class.

Spring Bean: Is autowired attribute initialised before constructor?

#Component
public class BeanA {
...
}
#Component
public class BeanB {
#Autowired
BeanA beanA;
public BeanB() {
// Use beanA
beanA.method();
}
}
Can we assume BeanA is created and initialized before BeanB constructor is called? (I know we can pass BeanA as constructor arg to BeanB, this is more of curiosity question to understand spring/java initialisation sequence)
Take a look at http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-autowired-annotation-qualifiers
Setting properties on bean would happen after it is constructed by means of a constructor or a factory method. By default, beans are autowired by name and values are set using setter methods. So in your case the field will be set after constructor.
This is because
#Autowired
BeanA beanA;
really means that you want to autowire the field of that class instance. beanA in your case is not really a constructor arg.
(Well, here is a quick question, are the constructor argument names retained after compilation? Is there any debug flag related to this?)
As this example from spring documentation says, you can apply #Autowired to constructors and fields:
public class MovieRecommender {
#Autowired
private MovieCatalog movieCatalog;
private CustomerPreferenceDao customerPreferenceDao;
#Autowired
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
Let me know if you need any more help with this.
Oh, and just a minor point. You seem to be calling method() on beanA in your constructor. It is not a good idea, if the method can be overridden. I know it is just an example you jotted down here, but just a word of caution.
No, the autowiring is handled by a BeanPostProcessor that will run after the constructor of the newly created bean. If, for some reason, you need to autowire some fields and then run some initialisation you can use a #PostConstruct annotated method. It will be called after all dependencies are injected. In most cases #Autowiring a constructor (and, perhaps, making the object immutable) is still the best option.
No, spring is very clever, but not that magical ... Internally, spring :
creates an instance
set instances properties
stores eventually the bean in relevant scope (exept for prototype beans) and/or gives it to caller
But the creation uses a constructor and at the time it is called properties have not been set.
In short, you can access #Autowired in your method marked with #PostConstruct.

How do I prevent Spring from instantiating a prototype scoped bean on context refresh?

I am using prototype scoped bean definitions in my Spring XML descriptors to configure the default properties (these beans have many properties) and then I call the application context with a getBean(beanName, ctorArgs[]) to create instances.
The bean definitions require 2-3 constructor arguments that supply logically unique keys used for things like key properties for the JMX ObjectName etc. Additionally, the variables that the constructor arguments are written to are final.
What I am seeing is that when the application context refreshes, it attempts to instantiate these prototypes, which seems completely the opposite of what you want prototypes to do. They're templates, not actual instances. To work around this, I have been configuring the prototypes with bogus ctor values so these bogus bean instances are instantiated and I simply filter out the created MBeans later in the code.
My question is, how do I configure the application context to register these prototype bean definitions, but not instantiate them until I make a getBean call ?
UPDATE:
The problem is a bit more complicated than I initialy thought. In fact, lazy is the default behaviour for prototype-scoped beans. I digged a bit and I managed to reproduce your problem and find the solution. So what is the problem?
You probably have <aop:scoped-proxy/> enabled or (#ComponentScan(scopedProxy=...) equivalent). During context refresh Spring wraps your prototype bean (ClosedMetricSubscriberFeed) with scoped proxy. It uses class proxy because (a) class proxies are chosen or (b) the class has no interfaces.
The class-based proxy is basically a CGLIB subclass of your bean that must call (due to JVM rules) a base class's constructor. And CGLIB generated class always calls no-arg constructor.
I know this sounds complicated, here's what you can do:
Disable <aop:scoped-proxy/>. Just like that.
Provide a dummy no-arg constructor and deprecate it just in case. Unfortunately you will have to discover such bogus instances manunally. Note that in this case the class will be of type: ``.
Extract an interface from your class and use interfaces for scoped proxies:
.
#Scope(
value = ConfigurableBeanFactory.SCOPE_PROTOTYPE,
proxyMode = ScopedProxyMode.INTERFACES)
Old answer:
Use lazy initialization with #Lazy annotation or lazy-init="true" (see 4.4.4 Lazy-initialized beans in reference documentation) configuration attribute.
<bean id="proto" class="MyPrototype" scope="prototype" lazy-init="true"/>
or:
#Service
#Scope("prototype")
#Lazy
public class MyPrototype {/*...*/}
I use a private, deprecated, no-arg constructor that throws an IllegalStateException. The context loads fine, getBean() with the constructor args works fine, and getBean() without args throws the exception.
package a;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
#Component("myCommand")
#Scope("prototype")
public class Command {
final protected String name;
#Deprecated
private Command() {throw new IllegalStateException("Only for Spring"); }
public Command(String name) {
super();
this.name = name;
}
#Override
public String toString() {
return "Command [name=" + name + "]";
}
}

Autowiring doubts in spring?

After going thru autowiring concept
i have got some questions. These are:-
If i need to autowire below class byType or byName , is it mandatory to have setStudent() method in class College?
public class College {
private Student student1;
private String registration1;
}
<bean id="student1" class="Student"/> - in case of byname it will look into id attribute and in case of bytype it will look for class attribute in above
Stetement. Right? If incase it finds two bean dean tags for the same type it will throw fatal error in case of bytype. Correct?
autodetect Scenario chooses constructor or byType through introspection of the bean class. If a default constructor is found, the byType mode
will be applied.
My question here if default constructor is not found and constructor with argument is found then autowire by constructor
will be applied. Correct?
Do we need to specify #Autowired somewhere in College to apply the autowiring. As i can see this in this example
but nothing is specified here
1), 4) There are two separate ways of autowiring in Spring: XML-based and annotaion-based.
XML-based autowiring is activated from XML config, as described here. In the end, it will call setter method, so setStudent() method is required here.
Annonation-based autowiring, on the other hand, is performed via reflection magic. It attempts to fill everything you mark with #Autowired annotation. In fact, it can set private field with no accessors, as in
public class Foo {
#Autowired private Thingy thing; // No getThing or setThing methods
private void doStuff() {
// thing is usable here
}
}
For #Autowired annotaion to work, you will need to define corresponding bean post-processor; it is done by adding the following line to xml config:
<context:annotation-config/>
Note, that these two autowiring methods are independant, and it is possible(but not recommended) to use them simultaneously. In that case, xml autowiring will override annotations.
2) In general, autowiring will fail, if it cannot find one and only one candidate for injection. So, in your case, it will fail with exception upon container creation. There are some fallback quirks, but in general it works reliably.
3) Yes, documentaion says so.
About byName and byType autowiring. While byName autowiring simply tries to match bean name (can be specified with id attribute), byType is a bit more complex than class attribute lookup. It searches beans by type, and it will match interfaces. Example:
public interface SomeService {
void doStuff();
}
public class SomeServiceImpl implements SomeService {
#Override public void doStuff() {
// Implementation
};
}
public class ServiceUser {
#Autowired
private SomeService someService; // SomeServiceImpl instance goes here
}
P.S. You are referencing two different versions of Spring in your question, 2.5 and 3.0. Autowiring behavior is same in both.
In Addition if you are using #Autwired annotation you need to mark the classes as candidates for autowiring. It should be done by using one of these annotations:
#Repository
#Service
#Component
#Controller
and of cause you can configure it in different scopes:
#Scope("prototype")
#Repository
public class MovieFinderImpl implements MovieFinder {
// ...
}
Hope it makes it more clear.

Resources