When should we use #Component in Spring? - java

From a software design perspective, when should we use #Component instead of a traditional Java class (that needs to be explicitly instantiated by 'new')? For example, if we need to create a class that is one of the following patterns:
Adapter
Bridge
Façade
Strategy
Translator
Should the class have the #Component annotation (or any Spring derivative annotation such as #Repository/#Controller/#Service)?

Spring applies the Inversion of Control principle, which drills down to that the framework handles stuff for you, so you don't have to worry about it.
By using #Component on the class you let Spring create a bean for you.
This way Spring can, for example, inject this bean on runtime when you need it. (For example by Autowiring your constructor).
It is up to you to decide if you want to make use of this functionality for your class. A facade for example could very well be a Spring component, this way you could possibly inject an API implementation that is exposed via a facade on runtime, without the need to think about the dependency injection implementation.
I would not recommend using this annotation on a DTO or model class for example. These classes mostly consist of data and don't fit the need to be managed by Spring.
Other interesting related questions that can help you decide when to create a component:
What's the difference between #Component, #Repository & #Service annotations in Spring?
Spring: #Component versus #Bean

Related

Spring: Why use #Service classes instead of Singleton objects?

We’re using Scala with Spring Boot, so creating Singleton objects is as simple as using the Scala ‘object’ keyword instead of the ‘class’ keyword, and filling it with whatever functions are needed. So far, it seems that Singleton objects can do the same thing as #Service classes, and also has the extra benefit of avoiding circular dependency errors during dependency injection. Is there any reason to use #Service classes over Singletons?
Annotating classes with #Service means that a Spring-managed bean will be created for such classes. By default, they are also singletons. However, being Spring-managed beans make it possible to use Spring-related features, such as:
Dependency injection (being this bean injected in other Spring-managed beans and also inject other Spring-managed beans into this one);
Spring AOP (allowing, for example, the usage of #Transactional);
Application context changes awareness (you could make your #Service implement ApplicationListener so that you can do something based on Application related events);
etc...

When to use service or component in spring? [duplicate]

This question already has answers here:
What's the difference between #Component, #Repository & #Service annotations in Spring?
(31 answers)
Closed 4 years ago.
When to use service or component in spring?
For example, is a module responsible for sending email or common business logic a "service" or a "component"?
and what's the difference?
Is a service able to call the other services?
Is there any transaction problem? or a service should call the components only?
Someone told me that a service should never call the other services and should only call the components instead, which means Controller->Service->Component->DAO, but I found many people share the concept of Controller->Service->DAO with no component.
Is there any system design criteria about this topic in Spring?
In order to "configure" Spring so it can provide you with the instances of the classes you need, you are supposed to tell Spring what objects are involved and how they are built. To do this you can use an xml configuration file or through annotations
In case you take the annotation approach (IMHO a much better and simpler one) you can use #Component to annotate the class. This is like telling Spring: "Hey! I want you to know that you may need an instance of this class. Maybe because I request it, maybe because something I requested needs it". So annotating a class with #Component just let Spring know that it exists
There are other annotations that do the same:
#Controller (and #RestController)
#Service
#Repository
They all inform Spring that the class is involved in the DI context. But they also have semantic meaning:
#Controller = #Component belonging to Presentation Layer
#Service = #Component belonging to Service/Use Case Layer
#Repository = #Component belonging to Persistence Layer
You can find more info in this question
Should a service be able to call the other services?
I don't see any problem with that. If any of your services requires to do some actions that are already performed by other you surely want to avoid code duplication. As long as you respect the architecture layers dependency (never going up) you'll be fine.
About this you can check this article about Clean Architecture
#Component is generic for other stereotypes.
So you can replace
#Repository, #Service, #Controller with #Component and nothing will change. But for better readability you should use #Repository, #Service, #Controller

Annotating simple POJO as #Component in Spring for enhancing behavior

I should be able to enhanced some POJO returned by some Spring controllers. To do that and detect those that should be enhanced, I want the developper to be able to put a class annotation on the POJO. The enhancing is doing both by combining a #ControllerAdvice that intercept the call and the detection of this special annotation on the returned POJOs to enhanced them. Getting the list of POJO that are candidate to the decoration by detecting them at the launch of the application instead of doing it dynamically when analyzing the response of the controller in the #ControllerAdvice would be of great benefit in term of performance.
In Spring, is it acceptable to use a custom annotation inheriting #Component to flag some simple POJO classes not aiming at being instantiated and managed by Spring with the simple goal to be able to get the list of them through
ClassPathScanningCandidateComponentProvider or should I preferably use some other third party library like Reflections to do the job?
My point is to not pervert the meaning of #Component just for the confort of the annotation scanning mechanism offered by Spring if #Component has no sense in this case.
We finally chose the following method: https://stackoverflow.com/a/1415338/256561 based on custom use of ClassPathScanningCandidateComponentProvider.

How to know which bean was injected into interface?

So I have a set packages that are my base code for extended applications. My application implements a series of interfaces that then are inject by spring during run time (As configured). I would like to know is there is a way that I could know which class that implements the interface was injected. I need this because I have JSON serializer/deserializer actions that I would like to perform but for that I need to know the class that was injected.
I have an java config file that will describe the wiring and it will be provided with the game implementation. But so far I haven't been able to get the concrete class implementing the interface. I also haven't been successful to request that info from the context.
Ant hints?
You can use reflection to let the injected instance tell you what implementation class it is: injectedInstance.getClass().getName(). However, unless you're doing something special, consider this a hack. You probably should revisit your design so that you do not need to do that.
You can simply autowire an interface and get the implemented class name:
#Autowired
private Service service;
System.out.println(service.getClass().getName());
However with Spring beans the spring container has usually proxied them so it's not always helpful, in the case above the class is a Spring class called:
hello.HelloServiceImpl$$EnhancerBySpringCGLIB$$ad2e225d
I suspect you should look at Jackson serializers which should handle all this, see Java - Jackson Annotations to handle no suitable constructor
So the way I came around this issue was by injecting an object into the JSON deserializer and use a getClass() method as the template to Jackson to use. And it worked like a charm, even thought the implementation to be injected was injected into a wiring happening in the dependency!. Hope it helps!

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.

Categories

Resources