Reputation: 6532
I was thinking about some of my services. Some of them looks like this:
@Service
public class UserService {
@Autowired
UserDao dao;
@Autowired
OtherService1 serv1;
@Autowired
OtherService2 serv2;
@Autowired
OtherService3 serv3;
....
}
I was thinking.. if this concept of autowiring other services into a single service is pretty common, why not creating a "Master-service" :
@Service
public class MasterService {
@Autowired
OtherService1 serv1;
@Autowired
OtherService2 serv2;
@Autowired
OtherService3 serv3;
...
@Autowired
LastService servN;
}
and autowiring this service in to all services.
@Service
public class AnyService {
@Autowired
MasterService masterSevice;
}
this way we wont have many services per service, but only a single one to rule them all..
Two questions rises:
1) Since masterService contain all services we have a loop in injection. can we solve it?
2) if the answer to question 1 is "yes" - is this "masterService" a good practice?
Upvotes: 1
Views: 4460
Reputation: 2486
1) Spring is able to handle dependency loops in many cases, especially when not using constructor injections.
2) Despite this. You should absolutely avoid this design. It breaks many principles of good architecture:
Breaking such principles may lead to bad situations such as:
The advantages you gain from such a design are very small (you just avoid a few @Autowired
annotations) and are not worth the risk.
Upvotes: 2
Reputation: 1
I haven't come across such pattern before (one service containing other services). What I commonly seen and used is something like below -
*SpecificController1 --> SpecificService1 --> SpecificDao1
SpecificController2 --> SpecificService2 --> SpecificDao2
Now, if SpecificService1 needs some functionality already available in SpecificService2, only then it will refer to SpecificService2.
So, I have few questions about the pattern described above:
Upvotes: 0
Reputation: 77177
1) MasterService
doesn't necessarily contain a loop. If it does, then you'll run into problems, and it's much simpler not to construct your beans in a loop in the first place.
2) It's possible for this to be effective if you're injecting into lots of short-lived beans, but this approach has the downside that anyone who meddles with the MasterService
instance can screw up the services for the other beans. You can hide this behind getter methods, but lumping everything together usually doesn't provide much benefit.
Instead, it's usually best to group related services together, maybe OtherService1
and OtherService2
, and to place them on an interface. This makes mocking for testing much easier and keeps related concepts together (ideally in their own jars/modules).
Upvotes: 0
Reputation: 1018
Why would have a circular dependency? There is one service that contains all the other services, and no other service that contains it. Having said that, a circular dependency could be easily solved by setting the dependency as property and not as constructor arg.
I don't think so, it is nice pattern to declare kind of hierarchy (in endpoints for instance), but what are the pros of it in this way? You can Autowire every service that you want also without it.
Upvotes: 1