This is my Spring repository interface.
#Repository
public interface WebappRepository extends CrudRepository<myModel, Long> {
}
In my controller, I can instantiate the WebappRepository even though it's an interface, because of Spring annotation magic.
public class controller{
#Autowire
WebappRepository repo;
public controller(){
}
}
But this variant, using the constructor, does not work, and rightly so, because WebappRepository is an interface.
public class controller{
WebappRepository repo;
public controller(){
this.repo = new WebappRepository();
}
}
Olivier Gierke himself advocates to avoid #Autowire fields at all costs. How can I "instantiate" the repository interface in my Spring application while avoiding the #Autowire?
Inject dependencies in constructor:
#Component
public class Controller{
WebappRepository repo;
#Autowire
public Controller(WebappRepository repo){
this.repo = repo;
}
}
If you're on Spring 4.3+ and your target class has just one constructor, you can omit autowired annotation. Spring will inject all the needed dependencies for it.
So writing just below constructor would suffice:
public controller(WebappRepository repo){
this.repo = repo;
}
Reference: https://docs.spring.io/spring/docs/4.3.x/spring-framework-reference/htmlsingle/#beans-autowired-annotation
Related
#Repository
public interface MyRepository extends CrudRepository<Custom, Long> {}
#Service
#RequiredArgsConstructor
public class MyServiceImpl implements MyServiceInterface {
private final MyRepository repository;
}
I use test configuration with instructions for bean construction for testing.
How to create #Bean for MyRepository interface?
#TestConfiguration
#EnableJpaRepositories(basePackages = "com.example.app")
public class TestBeans {
#Bean
MyServiceInterface getMyService() {
return new MyServiceImpl(getMyRepository());
}
#Bean
MyRepository getMyRepository() {
return null; // what should be here?
}
}
Just use #Autowire, spring will take care of bean creation if you had given #Repository on JPA interface.
If you look at the #Repository you noticed that this annotation is a stereotype of #Component. So when you use annotation #Repository this class will be treat as a bean (of course, if you enable jpa repositories).
#Target({ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME)
#Documented
#Component
public #interface Repository {
...
}
So if you want inject you repository into your bean, you can do like this:
#Bean
MyServiceInterface getMyService(MyRepository myRepository) {
return new MyServiceImpl(myRepository);
}
I have my custom starter. Inside it, I define a repository. How should I define it in the configuration? This is how I did the usual bean before.
#Bean
#ConditionalOnMissingBean(HelloWorldController.class)
public HelloWorldController helloWorldController() {
return new HelloWorldController();
}
Repository:
#Repository
public interface CarRepository extends JpaRepository<Car, Long> {
}
And configuration
#Configuration
#EnableJpaRepositories
public class DomainConfiguration {
}
If you use this starter, context will not see the repository bean. Because I did not declare it in the configuration.I don't know how to declare it.
Suppose I have a program
#Component
public interface Coach{
public String giveCoaching();
}
#Component
public TennisCoach implements Coach{
#Override
public String giveCoaching(){
return "Teaching forhand";
}
}
I have two Demo classes in which I have injected the bean in different ways. what is the difference in both the injections
public class AppDemo{
#AutoWired
#Qualifier("tennisCoach")
private Coach theCoach;
}
public class AppDemo{
#AutoWired
private TennisCoach tennisCoach;
}
}
When you have more than 1 implementation for you interface, you will get an exception when Autowiring the bean. At that time #Qualifier will be used to choose the required implementation
#Component
public interface Coach{
public String giveCoaching();
}
#Component
public TennisCoach implements Coach{
#Override
public String giveCoaching(){
return "Teaching forhand";
}
}
#Component
public CricketCoach implements Coach{
#Override
public String giveCoaching(){
return "Teaching forbat";
}
}
Now the ambiguity will occur when you autowire the Coach Interface like below
public class AppDemo{
#AutoWired
private Coach theCoach;
}
So you have to qualify the right bean for the CoachInterface like below.
public class AppDemo{
#AutoWired
#Qualifier("tennisCoach")
private Coach theCoach;
}
Alternatively you can use #Primary annotation on top of any one of the implementation so that the Spring Container will by default choose the bean in case of more than 1 implementation for an interface.
But in the code below, you are directly creating the object for the implementation rather than interface.
public class AppDemo{
#AutoWired
private TennisCoach tennisCoach;
}
}
#Qualifier annotation is used when your interface has more than one implementing class, You should opt for the one you want inject as a bean in spring context.
I need to have an interface and then two implementations in different maven modules. Both impl services see api modul with interface but they don't see each other.
There is a default implementation and then transactional implementation. I want transactional impl service just load and call default impl service. Like this:
package my.app.core.api;
public interface MyService {
boolean process();
}
package my.app.core.impl
#Service
public class MyServiceImpl implements MyService {
#Override
public boolean process() {
// do something cool...
}
}
package my.app.somewhere.else.impl
#Service
#Transactional
public class TransactionalMyServiceImpl implements MyService {
#Autowire
private MyService myService;
#Override
public boolean process() {
myService.process();
}
}
Is it possible or do I need to #Autowire explicitly MyServiceImpl instead of interface? Which means to add maven dependancy to my.app.somewhere.else.impl.pom.
You can give different names to your services like so:
#Service
#Qualifier("transactionalMyService")
And then when you autowire you can use the name:
#Autowired
#Qualifier("transactionalMyService")
private MyService myService;
I'm working on one project with Spring 4.2.4.RELEASE.
I've heard about new features Spring 4 (especially about autowiring of generic types), and I was confused when the following code hadn't been compiled:
#Service
public interface AuthenticationService<T> { ... }
public class VKAuthenticationService implements AuthenticationService<VKToken> { ... }
#RestController
public class VKAuthenticationController {
#Autowired
private AuthenticationService<VKToken> service;
}
Thank you in advance for any assistance.
How about also declare #Service on your VKAuthenticationService
#Service(name="myService")
public class VKAuthenticationService implements AuthenticationService<VKToken> { ... }
and use #Autowired and #Qualifier to inject it
#RestController
public class VKAuthenticationController {
#Autowired
#Qualifier("myService")
private AuthenticationService<VKToken> service;
}