简体   繁体   中英

Spring IoC - constructing context dependent beans?

Consider the following code:

@Service
class UserSpecificService {
    @Autowired ServiceA serviceA;
    @Autowired ServiceB serviceB;
    @Autowired User user;

    public void doUserSpecificThings() {
        // consume serviceA, serviceB and user here
    }
}

@Service class ServiceA {}
@Service class ServiceB {}

@Service
class Facade {
    public void doThingsForUser(Long userId) {
        User user = userService.getById(userId);
        UserSpecificService userSpecificService = ...; // !!!
        userSpecificService.doUserSpecificThings();
    } 
}

The question is about line marked with // !!! . Is there any way I can construct UserSpecificService without implementing my own factory which is aware of ServiceA and ServiceB , and only requires an instance of User to instantiate a UserSpecificService ?

If it matters - I'm going to use the Facade with Spring MVC, though I'd like it not to rely on this.

Thanks!

Here's a suggestion:

  • make all services that are eligible to be userSpecificService (I guess these are ServiceA and serviceB) have a common interface
  • let that interface have two methods - doUserSpecificThing() and isEligibleFor(user)
  • use @Autowired List<YourInterface> list
  • in your doThingsForUser() method iterate the list of all instances of the given interface, and for each of them check if it is eligible for the given user. If it is - invoke the method.

If you are asking if you can create a UserSpecificService dynamically without having to maunally set the services, try this:

@Configurable
class UserSpecificService {
    @Autowired private ServiceA serviceA;
    @Autowired private ServiceB serviceB;
    private User user;

    public UserSpecificService(User user){
        this.user = user;
    }

    public void doUserSpecificThings() {
        // consume serviceA, serviceB and user here
    }
}

@Service class ServiceA {}
@Service class ServiceB {}

@Service
class Facade {
    public void doThingsForUser(Long userId) {
        User user = userService.getById(userId);
        UserSpecificService userSpecificService = new UserSpecificService(user);
        userSpecificService.doUserSpecificThings();
    } 
}

Just be aware that you will need to configre your spring context to scan for @Configurable. To do this all you have to do is add <context:spring-configured/> to your application context file. Another approach would be:

@Service
class UserSpecificService {
    @Autowired private ServiceA serviceA;
    @Autowired private ServiceB serviceB;

    public void doUserSpecificThings(User user) {
        // consume serviceA, serviceB and user here
    }
}

@Service class ServiceA {}
@Service class ServiceB {}

@Service
class Facade {
    public void doThingsForUser(Long userId) {
        User user = userService.getById(userId);
        userSpecificService.doUserSpecificThings(user);
    } 
}

That approach may be better depending on your specific application.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM