Autowire specific implementations of persistence layer in Spring with Java based configuration - spring

In a Spring MVC proyect I'm using Spring Data in the persistence layer so I have a bunch of repositories to access the data. I also have a layer for services so I have things like UserService or AuthorityService that use that repositories.
The problem is that I've been asked to create an interface to be able to change the implementation of the persistence layer (using DAOs for example) without have to touch a single line in the services. How can I specify in an Autowired of that interface what implementation to use? I´m using Java based config and I don't see how to inject it.
I also have a problem with the name of these new interfaces. Normally I would use a name like UserService but Spring use Service for the service layer so, What name is suitable for this type of interface?

You could mark the new implementation of the DAO as #Primary. Indicates that a bean should be given preference when multiple candidates are qualified to autowire a single-valued dependency. If exactly one 'primary' bean exists among the candidates, it will be the autowired value.
#Component
public class FooService {
private FooRepository fooRepository;
#Autowired
public FooService(FooRepository fooRepository) {
this.fooRepository = fooRepository;
}
}
#Component
public class JdbcFooRepository {
public JdbcFooService(DataSource dataSource) {
// ...
}
}
#Primary
#Component
public class HibernateFooRepository {
public HibernateFooService(SessionFactory sessionFactory) {
// ...
}
}
Because HibernateFooRepository is marked with #Primary, it will be injected preferentially over the jdbc-based variant assuming both are present as beans within the same Spring application context, which is often the case when component-scanning is applied liberally.
This annotation is semantically equivalent to the element's primary attribute in Spring XML.
I didn't completely follow your second question.

Related

when using functional bean registration, is there a way to inform Spring that ClassA is responsible for creating an instance of BeanA?

I've switched a portion of a Spring app to use functional bean registrations. The motivation for the switch is due to requiring multiple instances of some beans under certain conditions. It also turns out to be much more concise (which won't be at all apparent with the simplistic examples below).
The code used to look like this (simple example):
#Configuration
public class ConfigA {
#Bean
public BeanA beanA() {
return new BeanA();
}
}
#Service
public class Service1 {
#Autowired BeanA beanA;
...
}
#Service
public class Service2 {
#Autowired BeanA beanA;
...
}
I've switched the configuration class to look like this:
#Configuration
public class ConfigA implements ApplicationContextInitializer<GenericApplicationContext> {
#Override
public void initialize(GenericApplicationContext context) {
context.registerBean("beanA", BeanA.class, () -> new BeanA());
}
}
The issue I'm now encountering is that Spring is complaining about autowired beans not being found. With the original code, Spring could determine that a BeanA bean was declared via ConfigA and would create that bean before initializing the services.
With the new code, I guess there is no way for Spring to determine where the BeanA bean(s) are being declared, and so it tries to init the services before the BeanA is initialized (which causes the app to not start).
I was hoping that Spring would prioritize #Configuration classes over #Service or #Controller classes, but that doesn't seem to be the case.
I could annotate all the services with #DependsOn("configA"), but there are many services that autowire BeanA (some in other code bases), so the #DependsOn option isn't really realistic.
Question: When using functional bean registration, is there a way to inform Spring that ConfigA is responsible for creating an instance of BeanA?
In order to use the functional style of bean registration and enable autowiring mechanism in other beans you can do the following:
Remove #Configuration annotation from your ConfigA class;
Create directory named META-INF under main/java/resources and create a file named spring.factories under the newly created directory;
Fill the newly created file with the line org.springframework.context.ApplicationContextInitializer=(package-name-to-configA-class).ConfigA
Now Spring should be able to successfully autowire bean named BeanA where requested.

No qualifying bean of type [org.springframework.mail.javamail.JavaMailSender] while deploying service into PCF [duplicate]

Please explain the following about NoSuchBeanDefinitionException exception in Spring:
What does it mean?
Under what conditions will it be thrown?
How can I prevent it?
This post is designed to be a comprehensive Q&A about occurrences of NoSuchBeanDefinitionException in applications using Spring.
The javadoc of NoSuchBeanDefinitionException explains
Exception thrown when a BeanFactory is asked for a bean instance for
which it cannot find a definition. This may point to a non-existing
bean, a non-unique bean, or a manually registered singleton instance
without an associated bean definition.
A BeanFactory is basically the abstraction representing Spring's Inversion of Control container. It exposes beans internally and externally, to your application. When it cannot find or retrieve these beans, it throws a NoSuchBeanDefinitionException.
Below are simple reasons why a BeanFactory (or related classes) would not be able to find a bean and how you can make sure it does.
The bean doesn't exist, it wasn't registered
In the example below
#Configuration
public class Example {
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Example.class);
ctx.getBean(Foo.class);
}
}
class Foo {}
we haven't registered a bean definition for the type Foo either through a #Bean method, #Component scanning, an XML definition, or any other way. The BeanFactory managed by the AnnotationConfigApplicationContext therefore has no indication of where to get the bean requested by getBean(Foo.class). The snippet above throws
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [com.example.Foo] is defined
Similarly, the exception could have been thrown while trying to satisfy an #Autowired dependency. For example,
#Configuration
#ComponentScan
public class Example {
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Example.class);
}
}
#Component
class Foo { #Autowired Bar bar; }
class Bar { }
Here, a bean definition is registered for Foo through #ComponentScan. But Spring knows nothing of Bar. It therefore fails to find a corresponding bean while trying to autowire the bar field of the Foo bean instance. It throws (nested inside a UnsatisfiedDependencyException)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [com.example.Bar] found for dependency [com.example.Bar]:
expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
There are multiple ways to register bean definitions.
#Bean method in a #Configuration class or <bean> in XML configuration
#Component (and its meta-annotations, eg. #Repository) through #ComponentScan or <context:component-scan ... /> in XML
Manually through GenericApplicationContext#registerBeanDefinition
Manually through BeanDefinitionRegistryPostProcessor
...and more.
Make sure the beans you expect are properly registered.
A common error is to register beans multiple times, ie. mixing the options above for the same type. For example, I might have
#Component
public class Foo {}
and an XML configuration with
<context:component-scan base-packages="com.example" />
<bean name="eg-different-name" class="com.example.Foo />
Such a configuration would register two beans of type Foo, one with name foo and another with name eg-different-name. Make sure you're not accidentally registering more beans than you wanted. Which leads us to...
If you're using both XML and annotation-based configurations, make sure you import one from the other. XML provides
<import resource=""/>
while Java provides the #ImportResource annotation.
Expected single matching bean, but found 2 (or more)
There are times when you need multiple beans for the same type (or interface). For example, your application may use two databases, a MySQL instance and an Oracle one. In such a case, you'd have two DataSource beans to manage connections to each one. For (simplified) example, the following
#Configuration
public class Example {
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Example.class);
System.out.println(ctx.getBean(DataSource.class));
}
#Bean(name = "mysql")
public DataSource mysql() { return new MySQL(); }
#Bean(name = "oracle")
public DataSource oracle() { return new Oracle(); }
}
interface DataSource{}
class MySQL implements DataSource {}
class Oracle implements DataSource {}
throws
Exception in thread "main" org.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type [com.example.DataSource] is defined:
expected single matching bean but found 2: oracle,mysql
because both beans registered through #Bean methods satisfied the requirement of BeanFactory#getBean(Class), ie. they both implement DataSource. In this example, Spring has no mechanism to differentiate or prioritize between the two. But such mechanisms exists.
You could use #Primary (and its equivalent in XML) as described in the documentation and in this post. With this change
#Bean(name = "mysql")
#Primary
public DataSource mysql() { return new MySQL(); }
the previous snippet would not throw the exception and would instead return the mysql bean.
You can also use #Qualifier (and its equivalent in XML) to have more control over the bean selection process, as described in the documentation. While #Autowired is primarily used to autowire by type, #Qualifier lets you autowire by name. For example,
#Bean(name = "mysql")
#Qualifier(value = "main")
public DataSource mysql() { return new MySQL(); }
could now be injected as
#Qualifier("main") // or #Qualifier("mysql"), to use the bean name
private DataSource dataSource;
without issue. #Resource is also an option.
Using wrong bean name
Just as there are multiple ways to register beans, there are also multiple ways to name them.
#Bean has name
The name of this bean, or if plural, aliases for this bean. If left
unspecified the name of the bean is the name of the annotated method.
If specified, the method name is ignored.
<bean> has the id attribute to represent the unique identifier for a bean and name can be used to create one or more aliases illegal in an (XML) id.
#Component and its meta annotations have value
The value may indicate a suggestion for a logical component name, to
be turned into a Spring bean in case of an autodetected component.
If that's left unspecified, a bean name is automatically generated for the annotated type, typically the lower camel case version of the type name. For example MyClassName becomes myClassName as its bean name. Bean names are case sensitive. Also note that wrong names/capitalization typically occur in beans referred to by string like #DependsOn("my BeanName") or XML config files.
#Qualifier, as mentioned earlier, lets you add more aliases to a bean.
Make sure you use the right name when referring to a bean.
More advanced cases
Profiles
Bean definition profiles allow you to register beans conditionally. #Profile, specifically,
Indicates that a component is eligible for registration when one or
more specified profiles are active.
A profile is a named logical grouping that may be activated
programmatically via
ConfigurableEnvironment.setActiveProfiles(java.lang.String...) or
declaratively by setting the spring.profiles.active property as a JVM
system property, as an environment variable, or as a Servlet context
parameter in web.xml for web applications. Profiles may also be
activated declaratively in integration tests via the #ActiveProfiles
annotation.
Consider this examples where the spring.profiles.active property is not set.
#Configuration
#ComponentScan
public class Example {
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Example.class);
System.out.println(Arrays.toString(ctx.getEnvironment().getActiveProfiles()));
System.out.println(ctx.getBean(Foo.class));
}
}
#Profile(value = "StackOverflow")
#Component
class Foo {
}
This will show no active profiles and throw a NoSuchBeanDefinitionException for a Foo bean. Since the StackOverflow profile wasn't active, the bean wasn't registered.
Instead, if I initialize the ApplicationContext while registering the appropriate profile
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.getEnvironment().setActiveProfiles("StackOverflow");
ctx.register(Example.class);
ctx.refresh();
the bean is registered and can be returned/injected.
AOP Proxies
Spring uses AOP proxies a lot to implement advanced behavior. Some examples include:
Transaction management with #Transactional
Caching with #Cacheable
Scheduling and asynchronous execution with #Async and #Scheduled
To achieve this, Spring has two options:
Use the JDK's Proxy class to create an instance of a dynamic class at runtime which only implements your bean's interfaces and delegates all method invocations to an actual bean instance.
Use CGLIB proxies to create an instance of a dynamic class at runtime which implements both interfaces and concrete types of your target bean and delegates all method invocations to an actual bean instance.
Take this example of JDK proxies (achieved through #EnableAsync's default proxyTargetClass of false)
#Configuration
#EnableAsync
public class Example {
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Example.class);
System.out.println(ctx.getBean(HttpClientImpl.class).getClass());
}
}
interface HttpClient {
void doGetAsync();
}
#Component
class HttpClientImpl implements HttpClient {
#Async
public void doGetAsync() {
System.out.println(Thread.currentThread());
}
}
Here, Spring attempts to find a bean of type HttpClientImpl which we expect to find because the type is clearly annotated with #Component. However, instead, we get an exception
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [com.example.HttpClientImpl] is defined
Spring wrapped the HttpClientImpl bean and exposed it through a Proxy object that only implements HttpClient. So you could retrieve it with
ctx.getBean(HttpClient.class) // returns a dynamic class: com.example.$Proxy33
// or
#Autowired private HttpClient httpClient;
It's always recommended to program to interfaces. When you can't, you can tell Spring to use CGLIB proxies. For example, with #EnableAsync, you can set proxyTargetClass to true. Similar annotations (EnableTransactionManagement, etc.) have similar attributes. XML will also have equivalent configuration options.
ApplicationContext Hierarchies - Spring MVC
Spring lets you build ApplicationContext instances with other ApplicationContext instances as parents, using ConfigurableApplicationContext#setParent(ApplicationContext). A child context will have access to beans in the parent context, but the opposite is not true. This post goes into detail about when this is useful, particularly in Spring MVC.
In a typical Spring MVC application, you define two contexts: one for the entire application (the root) and one specifically for the DispatcherServlet (routing, handler methods, controllers). You can get more details here:
Difference between applicationContext.xml and spring-servlet.xml in Spring Framework
It's also very well explained in the official documentation, here.
A common error in Spring MVC configurations is to declare the WebMVC configuration in the root context with #EnableWebMvc annotated #Configuration classes or <mvc:annotation-driven /> in XML, but the #Controller beans in the servlet context. Since the root context cannot reach into the servlet context to find any beans, no handlers are registered and all requests fail with 404s. You won't see a NoSuchBeanDefinitionException, but the effect is the same.
Make sure your beans are registered in the appropriate context, ie. where they can be found by the beans registered for WebMVC (HandlerMapping, HandlerAdapter, ViewResolver, ExceptionResolver, etc.). The best solution is to properly isolate beans. The DispatcherServlet is responsible for routing and handling requests so all related beans should go into its context. The ContextLoaderListener, which loads the root context, should initialize any beans the rest of your application needs: services, repositories, etc.
Arrays, collections, and maps
Beans of some known types are handled in special ways by Spring. For example, if you tried to inject an array of MovieCatalog into a field
#Autowired
private MovieCatalog[] movieCatalogs;
Spring will find all beans of type MovieCatalog, wrap them in an array, and inject that array. This is described in the Spring documentation discussing #Autowired. Similar behavior applies to Set, List, and Collection injection targets.
For a Map injection target, Spring will also behave this way if the key type is String. For example, if you have
#Autowired
private Map<String, MovieCatalog> movies;
Spring will find all beans of type MovieCatalog and add them as values to a Map, where the corresponding key will be their bean name.
As described previously, if no beans of the requested type are available, Spring will throw a NoSuchBeanDefinitionException. Sometimes, however, you just want to declare a bean of these collection types like
#Bean
public List<Foo> fooList() {
return Arrays.asList(new Foo());
}
and inject them
#Autowired
private List<Foo> foos;
In this example, Spring would fail with a NoSuchBeanDefinitionException because there are no Foo beans in your context. But you didn't want a Foo bean, you wanted a List<Foo> bean. Before Spring 4.3, you'd have to use #Resource
For beans that are themselves defined as a collection/map or array
type, #Resource is a fine solution, referring to the specific
collection or array bean by unique name. That said, as of 4.3,
collection/map and array types can be matched through Spring’s
#Autowired type matching algorithm as well, as long as the element
type information is preserved in #Bean return type signatures or
collection inheritance hierarchies. In this case, qualifier values can
be used to select among same-typed collections, as outlined in the
previous paragraph.
This works for constructor, setter, and field injection.
#Resource
private List<Foo> foos;
// or since 4.3
public Example(#Autowired List<Foo> foos) {}
However, it will fail for #Bean methods, ie.
#Bean
public Bar other(List<Foo> foos) {
new Bar(foos);
}
Here, Spring ignores any #Resource or #Autowired annotating the method, because it's a #Bean method, and therefore can't apply the behavior described in the documentation. However, you can use Spring Expression Language (SpEL) to refer to beans by their name. In the example above, you could use
#Bean
public Bar other(#Value("#{fooList}") List<Foo> foos) {
new Bar(foos);
}
to refer to the bean named fooList and inject that.

Spring create bean only if condition is met

Assume there are two implementations of a single interface, and these beans are declared as beans in the spring configuration xml. Now, I would need only one implementation of the interface based on the system property. And, I don't wanna create the second implementation of the bean. How can I do this? I looked at this blog but then below snippet of the code from this blog uses "new" operate to create the beans. In my case the beans are declared in the spring configuration file.
http://www.intertech.com/Blog/spring-4-conditional-bean-configuration/
#CONFIGURATION
PUBLIC CLASS MYCONFIGURATION {
#BEAN(NAME="EMAILERSERVICE")
#CONDITIONAL(WINDOWSCONDITION.CLASS)
PUBLIC EMAILSERVICE WINDOWSEMAILERSERVICE(){
RETURN NEW WINDOWSEMAILSERVICE();
}
#BEAN(NAME="EMAILERSERVICE")
#CONDITIONAL(LINUXCONDITION.CLASS)
PUBLIC EMAILSERVICE LINUXEMAILERSERVICE(){
RETURN NEW LINUXEMAILSERVICE();
}

Where should #Service annotation be kept? Interface or Implementation?

I'm developing an application using Spring. I need to use the #Service annotation. I have ServiceI and ServiceImpl such that ServiceImpl implements ServiceI. I'm confused here as to where should I keep the #Service annotation.
Should I annotate the interface or the implementation with #Service? What are the differences between these two approaches?
I never put #Component (or #Service, ...) at an interface, because this make the interface useless. Let me explain why.
claim 1: If you have an interface then you want to use that interface for the injection point type.
claim 2: The purpose of an interface is that it define a contract that can been implemented by several implementations. On the other side you have your injection point (#Autowired). Having just one interface and only one class that implement it, is (IMHO) useless, and violates YAGNI.
fact: When you put:
#Component (or #Service, ...) at an interface,
have multiple classes that implements it,
at least two classes become Spring Beans, and
have an injection point that use the interface for type based injection,
then you will get and NoUniqueBeanDefinitionException
(or you have a very special configurations setup, with Environment, Profiles or Qualifiers ...)
Conclusion: If you use #Component (or #Service, ...) at an interface then you must violate at least one of the two clains. Therefore I think it is not useful (except some rare scenarios) to put #Component at interface level.
Spring-Data-JPA Repository interfaces are something complete different
Basically annotations like #Service, #Repository, #Component, etc. they all serve the same purpose:
auto-detection when using annotation-based configuration and classpath
scanning.
From my experience I am always using #Service annotation on the interfaces or abstract classes and annotations like #Component and #Repository for their implementation. #Component annotation I am using on those classes which serves basic purposes, simple Spring beans, nothing more. #Repository annotation I am using in the DAO layer, for e.g. if I have to communicate to the database, have some transactions, etc.
So I would suggest to annotate your interface with the #Service and other layers depending on the functionality.
I used #Component, #Service, #Controller and #Repository annotations only on the implementation classes and not on the interface. But #Autowired annotation with Interfaces still worked for me. If there's only one implementation of your interface Spring component scan automatically finds it with just #Autowired annotation. In case you have multiple implementations, you will need to use the #Qualifier annotation along with #Autowired to inject the correct implementation at the injection point.
1. #Service on Interfaces
#Service
public interface AuthenticationService {
boolean authenticate(String username, String password);
}
Normally, that's fine, but there's a drawback. By putting Spring's #Service on interfaces, we create an extra dependency and couple our interfaces with an outside library.
Next, to test the autodetection of our new service beans, let's create an implementation of our AuthenticationService:
public class InMemoryAuthenticationService implements AuthenticationService {
#Override
public boolean authenticate(String username, String password) {
//...
}
}
We should pay attention that our new implementation, InMemoryAuthenticationService, doesn't have the #Service annotation on it. We left #Service only on the interface, AuthenticationService.
So, let's run our Spring context with the help of a basic Spring Boot setup:
#SpringBootApplication
public class AuthApplication {
#Autowired
private AuthenticationService authService;
public static void main(String[] args) {
SpringApplication.run(AuthApplication.class, args);
}
}
When we run our app, we may get the infamous NoSuchBeanDefinitionException, and the Spring context fails to start.
Therefore, placing #Service on interfaces isn't enough for the auto-detection of Spring components.
2. #Service on Abstract Classes
Using the #Service annotation on abstract classes isn't common.
We'll start by defining an abstract class from scratch and putting the #Service annotation on it:
#Service
public abstract class AbstractAuthenticationService {
public boolean authenticate(String username, String password) {
return false;
}
}
Next, we extend AbstractAuthenticationService to create a concrete implementation without annotating it:
public class LdapAuthenticationService extends AbstractAuthenticationService {
#Override
public boolean authenticate(String username, String password) {
//...
}
}
Accordingly, we also update our AuthApplication, to inject the new service class:
#SpringBootApplication
public class AuthApplication {
#Autowired
private AbstractAuthenticationService authService;
public static void main(String[] args) {
SpringApplication.run(AuthApplication.class, args);
}
}
After we run our AuthApplication, the Spring context doesn't start. It ends up with the same NoSuchBeanDefinitionException exception again.
So, using #Service annotation on abstract classes doesn't have any effect in Spring.
3. #Service on Concrete Classes
Contrary to what we've seen above, it's quite a common practice to annotate the implementation classes instead of abstract classes or interfaces.
In this way, our goal is mostly to tell Spring this class is going to be a #Component and mark it with a special stereotype, which is #Service in our case.
Therefore, Spring will autodetect those classes from the classpath and automatically define them as managed beans.
So, let's put #Service on our concrete service classes this time around. We'll have one class that implements our interface and a second that extends the abstract class that we defined previously:
#Service
public class InMemoryAuthenticationService implements AuthenticationService {
#Override
public boolean authenticate(String username, String password) {
//...
}
}
#Service
public class LdapAuthenticationService extends AbstractAuthenticationService {
#Override
public boolean authenticate(String username, String password) {
//...
}
}
We should take notice here that our AbstractAuthenticationService doesn't implement the AuthenticationService here. Hence, we can test them independently.
Finally, we add both of our service classes into the AuthApplication and give it a try:
#SpringBootApplication
public class AuthApplication {
#Autowired
private AuthenticationService inMemoryAuthService;
#Autowired
private AbstractAuthenticationService ldapAuthService;
public static void main(String[] args) {
SpringApplication.run(AuthApplication.class, args);
}
}
Our final test gives us a successful result, and the Spring context boots up with no exceptions. Both of the services are automatically registered as beans.
You might have a look at this page for the other explanations.
Pros of putting annotation on #Service is that it gives a hint that it is a service. I don't know if any implementing class will by default inherit this annoation.
Con side is that you are coupling your interface with a specific framework i.e. Spring, by using spring specific annotation.
As interfaces are supposed to be decoupled from implementation, I would not suggest using any framework specific Annotations or object part of your interface.
I would put #Service on your class but put the name of the interface as a parameter to the annotation e.g.
interface ServiceOne {}
#Service("ServiceOne")
class ServiceOneImpl implements ServiceOne{}
By doing that you get all the benefits and can still inject the interface but get the class
#Autowired
private ServiceOne serviceOne;
So your interface is not tied to spring framework and you can change the class at any time and not have to update all your injection points.
So if I wanted to change the implementation class I could just annotate the new class and remove from the first but that's all that is required to be changed. If you inject the class you could have a lot of work when ever you want to change the impl class.
One benefit of spring is to easily switch Service (or other) implementation.
For this, you need to annotate on the interface and declare variable like this :
#Autowired
private MyInterface myVariable;
and not :
#Autowired
private MyClassImplementationWhichImplementsMyInterface myVariable;
Like the first case, you can activate which implementation to inject from the moment it is unique (only one class implements the interface).
In the second case, you need to refactor all your code (the new class implementation has another name).
As a consequence, the annotation needs to be on the interface as much as possible. Furthermore, JDK proxies are well suited for this : they are created and instantiated at application startup because runtime type is known by advance, contrary to CGlib proxies.
interface MyService {}
#Service
class MyServiceImpl implements MyService{}
#Autowired
private MyService myService;
My testing result on spring-boot 2.7.4 is:
Adding #Service ONLY to interface doesn't create spring bean named MyService. It will error on Autowired.
#Service will need to be added to implementation class to create bean com.*.service.impl.MyServiceImpl $$EnhancerBySpringCGLIB$$9140ae19 Spring will wire it to private MyService myService;
There are 5 annotations which could be used for making spring beans. List in below of answers.
Do you really need an interface? If you are going to have one implementation for each service interface, just avoid it, use only class. Of course, if you don't have RMI or when interface proxy is required.
#Repository - use for injecting your dao layer classes.
#Service - use for injecting your service layer classes. In service layer also you might need to use #Transactional annotation for db transaction management.
#Controller - use for your frontend layer controllers, such as JSF managed beans injecting as spring beans.
#RestController - use for spring rest controllers, this would help you to avoid every time to put #ResponseBody and #RequestBody annotations in your rest methods.
#Component - use it in any other case when you need to Inject spring bean which is not controller, service, or dao class
To put it simply:
#Service is a Stereotype annotation for the service layer.
#Repos­itory is a Stereotype annotation for the persis­tence layer.
#Component is a generic stereotype annotation used to tell Spring to create an instance of the object in the Appl­ication Context. It's possible to
define any name for the instance, the default is the class name as camel case.

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