I am reading the book Pro Spring 3. It has a certain paragraph that really confused me. The paragraph is about autowiring in spring. Here is an excerpt:
In most cases, the answer to the question of whether you should use
autowiring is definitely “no!” Autowiring can save you time in small
applications, but in many cases, it leads to bad practices and is
inflexible in large applications. Using byName seems like a good
idea, but it may lead you to give your classes artificial property
names so that you can take advantage of the autowiring functionality.
The whole idea behind Spring is that you can create your classes how
you like and have Spring work for you, not the other way around ...
... For any nontrivial application, steer clear of autowiring at all
costs.
I have always been using the #Autowired tag in applications I have created. Can someone explain what is wrong with it and what I should use instead?
A mini example on how I handle most things now is:
#Service("snippetService")
public class SnippetService {
#Autowired
private TestService testService;
public Snippet getSnippet() {
return testService.getSnippet();
}
}
Is using autowiring like this "wrong" or am I missing something?
I believe there are two things confused here. What is meant by 'autowiring' in this chapter is marking bean for automated detection and injection of dependencies. This can be achieved through setting of "autowire" bean attribute.
This is in fact opposed to using #Autowired where you explicitely indicate field or setter for dependency injection.
Have a look here: http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/beans.html#beans-factory-autowire.
To explain it, assume you have
public class SnippetService {
private TestService testService;
public Snippet getSnippet() {
return testService.getSnippet();
}
public void setTestService(TestService testService) {
this.testService = testService;
}
}
If you defined a bean:
<bean class="mypackage.SnippetService" autowire="byType"/>
spring would attempt to inject bean of matching type, TestService in this case, by calling setTestService setter. Even though you did not use #Autowired. This indeed is dangerous since some setters might not be meant to be called by spring.
If you set autowire="no", nothing will be injected unless marked so with #Autowired, #Resource, #Inject.
There's nothing wrong with what you have, especially if you are starting out with one implementation of TestService anyways. As Johan mentions though, it's better to use #javax.annotation.Resource which also allows you to be more specific if you need to (for example using the name or the type attribute).
The only problem I see here is that you are loosing control a little. For example, say you have two or more instances of TestService in your app config and you want to use one of them. Having Autowire makes is trickier than using config XML to inject for you. This is what your book is trying to point i.e. it becomes difficult/trickier in big application where such needs are more frequent.
If you don't have such situations, I think its fine.
Autowire through XML is completely safe and helpful if you do constructor based autowiring particularly if you make the collaborators private final.
I'm kind shocked the author said that when I did the above on an extremely large spring 2.5 project a couple years ago. (at the time the annotation support was not working in JBoss)
Related
I have done my research before asking but no luck.
I have a StartUp Singleton bean. In this bean I have an #Inject #Any Instance. I loop all the implementations and try to check if the class is annotated with a custom annotation. All the implementations(all the classes that I want to inspect) are Stateful or Stateless beans.
Sometime the class I want is found and I can perform getClass().isAnnotationPresent(ClassNameAnnotation.class)
Most of the times I get a proxy object and in this case I cannot perform the above check.
I cannot find a way to get the real object. I have tried to get the SuperClass but not luck.
I will attach some of the code so you can have a better idea.
#Singleton
#Startup
public class CacheLoader {
#Inject
#Any
private Instance<ClassNameA> aClasses;
.......
#Lock(LockType.READ)
public void evaluate() {
if (!aClasses.isUnsatisfied()) {
for (ClassNameA className : aClasses) {
if (className.getClass().isAnnotationPresent(ClassNameAnnotation.class)) {
....
}
}
}
}
}
I tried to use the SuperClass of the proxy object but it does not return what I want. I tried also via Proxy.getInvocationHandler(). Even when I check the methods Proxy.isProxyClass(getClass()) or isSynthetic() does not return that the object is a proxy.
Thank you!
I think you would be better served by using a CDI Portable Extension, rather than a Singleton EJB. A couple of reasons
In CDI, everything is a proxy. So like some of the commenters have said, using reflection would be very fragile as it's not part of the spec. You're dealing with classes that are defined at runtime. It may work if you tie yourself to implementation-specific details, but it could break between releases of your CDI container.
The CDI Container will do all of the annotation scanning for you :)
A portable extension runs on startup, before other stuff starts flying around your app
A google search gave me this guide, but there are lots of them: https://www.baeldung.com/cdi-portable-extension
I think you would want to hook in processAnnotatedType() if you're modifying the bean declarations, or afterBeanDiscovery() if you're just documenting them as you said.
We actually have a CDI Portable Extension we use internally that does some config magic for environments. One of the config params is an annotation that is not a qualifier annotation, which sounds like what you want... the CDI container can get you the type, from which you can inspect the annotations.
Finally, this is not directed related to your question but may be useful: If your annotations drive configuration through fields of the annotations, selecting them can be quite complicated because of how the Java type and inheritance system works with annotations. You may benefit by using AnnotationLitreal in those cases. Read up here on this useful utility class here: http://www.kurtsparber.de/?p=387
EDIT:
Another side note... even thought I think you should switch to a Portable Extension, you shouldn't need #EJB's Singleton Startup anymore! you can do this with pure CDI: https://rmannibucau.wordpress.com/2015/03/10/cdi-and-startup/
I am learning Spring Boot and have quite a theoretical question. In this Udacity Example the
model class is initiated manually:
ChatMessage newMessage = new ChatMessage();
Is it good practice?
I will elaborate further on this. Let's say I have a DateUtil class that does some date conversions, should I register it using #Component annotation or manage its dependency myself (DateUtil dateUtil = new DateUtil())?
So the main summarized question: How to know when to use component annotations and when to initialize classes manually?
Thanks a lot!!!
The answer to the first question is, yes, it's still okay, because beans are assumed to be singletones, although not always. In this case, it makes no sense to mark the ChatMessage class as a bean, since instances of this class will be created many times and it is absolutely unclear what benefit will be obtained if they are all beans and are located in the application context.
Answer to the second question: I think the DateUtil class should be instantiated in the usual way, because it looks like a regular utility class like StringUtils. Perhaps you should make its methods static and then you won't have to instantiate it at all. But if this is a complex class that contains business logic and / or is initialized with some data received from outside the application when it starts and this object of this class is used in other classes of the application, then it may be worth making it a bean.
The answer to the third question: it is difficult to give an unambiguous answer. Beans are worth creating when you want to achieve an inversion of control and not depend on the class you are injecting. Declaring a class as a component so that its instances become beans must make sense, bring an advantage to the design of the application.
You need experience with Spring applications to understand when to make beans. Take a look at some well-known Spring applications to understand in which case and which class instances are beaned.
As I know, when you create class with #Component (I like use #Service), Spring will create bean inside IoC. Then you can use that bean by #Autowired, with #Component you create only one instance, that will be shared all over the application. When you use 'new' method to create object, you create object by yourself. Check more info in bean scope doc.
I have a Spring bean class which requests dependencies to be injected. However, in my class, I am manually wiring different dependencies to the same private class variable. What happens in this scenario? Which injection takes precedent?
Details:
I have created a Spring bean class called BadmintonCoach.
It relies on an IfortuneService helper. IfortuneService is an interface with TWO different implementations. The two implementations are:
FortuneService_RESTful
FortuneService_Random
In my badmintonCoach class, I have created a private variable to receive the injection from Spring:
private IFortuneService theFortuneService
That is to say, I am manually wiring up the the injected dependency to this private member, theFortuneService
I am injecting these iFortuneService dependencies using method injection.
BUT here is the problem: I have TWO methods, both of which request an injection from Spring of the type iFortuneService. One method requests one implementation (FortuneService_RESTful) and the other method requests a bean of the other implementation (FortuneService_Random).
Both of these methods set this.theFortuneService equal to its respective requested helper. So what I have within my BadmintonCoach class is:
private IFortuneService theFortuneService
#Autowired
#Qualifier("fortuneService_Random")
public void randomMethod_ONE(IFortuneService theFortuneService) {
System.out.println("Code inside randomMethod_ONE!");
this.theFortuneService = theFortuneService;
}
#Autowired
#Qualifier("fortuneService_RESTful")
public void randomMethod_TWO(IFortuneService theFortuneService) {
System.out.println("Code inside randomMethod_TWO!");
this.theFortuneService = theFortuneService;
}
My question then, is:
Which of the two wirings wins out? Why? How does Spring decide the ORDER of its injections? What determines the order of the injections? Is it random? Is it injected in alphabetic order of the method names? Is there an order of injection between constructor, setter, field and method injections?
What am I seeing when I run my program? I am seeing the injection of fortuneService_RESTful win out, but it is unclear to me whether this is by chance or by design from within Spring's logic.
Here is another thought:
What if, instead of requesting different implementations of the IFortuneService interface, the two methods above asked for the same bean but that bean was prototyped? Clearly, there would be a new incarnation created for each request and there would only be one helper class assigned to my BadmintonCoach class. But which incarnation would win out?
I can provide the whole of my code if it will make my question clearer.
If you are wondering WHY I have written conflicting code? It is plain and simple curiosity to try and understand how Spring works behind the scenes.
OK folks, it has taken a day for me to see this but I can confirm that what happens here is indeed random!
Yesterday, I was exclusively seeing method_ONE win out. Today, I am seeing method_TWO win out. I can therefore conclude that the order of injections by Spring is indeed random!
Thomas Klager had provided a suggestion in the comments above which may explain this phenomenon:
One obvious reason [for this] is that using annotation based injections, spring
needs to list the methods of a class using Class.getDeclaredMethods()
or Class.getMethods(). Neither of these methods return the methods in
any particular order.
I still find it a mystery how execution of the same logic by Spring (ie: Class.getDeclaredMethods() or Class.getMethods()) can yield random results like this.
It is very important to be aware of this limitation! When writing code, you may find yourself wanting to use the services of injected dependencies which in turn depend on the services other injected dependencies. It is clear from this experiment that this could potentially be dangerous and therefore you should not layer your wiring in this manner. That is to say, your wiring should always be single tiered if it spans multiple methods, otherwise, you risk spurious output from your program. An illustration of this danger can be seen in Slim's answer in this link.
Today, we found this pattern in our code:
class Foo {
private List<String> errors;
public void addError(String error) { ... }
public List<String> getErrors();
}
While the code seems to work, this is a singleton Spring bean and it's injected in several independent places and the consumers of the bean assume that they each have their own list of errors. So this introduces subtle bugs.
The obvious solution is to educate developers to avoid this kind of error but I was wondering if there is a static or runtime code analysis tool which can find this kind of bug.
For example, a bean postprocessor could analyze the bean before it's returned and look for private fields that aren't #Autowired.
After pouring some more brains (ours and other peoples) on this, we came up with this approach:
Install a BeanPostProcessor which makes sure that all singleton beans (i.e. where the scope in the bean definition is Singleton) have the custom annotation #Stateless on the actual bean type.
We chose a custom annotation instead of reusing #Singleton since we need this functionality elsewhere, too.
If the annotation is missing, the factory throws an error.
In a unit test, we use ClassPathScanningCandidateComponentProvider with out custom annotation to locate all classes on the classpath. We can then do the complex and expensive tests to make sure the bean has no state that changes after the initial configuration (i.e. after the autowiring has happened).
The second step could become a little bit easier if we moved the autowired fields into the constructor but we don't like methods that take many, many arguments. It would be nice if Java or an IDE could generate builders from the bean code. Since that's not the case, we stick to autowired fields and/or setters.
You could create a JUnit test that would load your app config.
This could combine ListableBeanFactory from here :
Can I dynamically create a List by scanning the beans in a spring configuration file?
with the 'isSingleton' check here :
How to enforce a prototype scope of Spring beans
i.e. list all the beans in the app context, then check to see which are singletons.
This would let you find all singleton beans...although it wouldn't really prevent your error case where someone treats one of these singletons as if it were not.
I am trying to let a piece of runtime state decide WHICH implementation of an interface to use, preferably solely by autowiring.
I have tried making an object factory for the interface thet uses dynamic proxies, and I used qualifiers to coerce the #Autowired injections to use the factory. The qualifiers are necessary because both the factory and the implementations respond to the same interface.
The problem with this is that I end up annotating every #Autowired reference with the #Qualifier. What I'd really want to do is annotate the non-factory implementations with something like #NotCandidateForAutowiringByInterface (my fantasy annotation), or even better make spring prefer the single un-qualified bean when injecting to an un-qualified field
I may thinking along the totally wrong lines here, so alternate suggestions are welcome.
Anyone know how to make this happen ?
You could use #Resource and specify the bean name of the factory.
I haven't looked at this myself but I noticed Spring JavaConfig is made it to M4 and it seems to allow more flexible configuration through a combination of annotations and Java code. I wonder if it would offer a solution to your problem.