javaspringdependency-injectionannotations

How to autowire with parameters in constructor?


I have a service that I want to be @Autowired, but it takes a complex object in constructor. How can I provide it using dependency injection?

@Service
class ProcessService
    @Autowired
    private PersonService service;
    
    public void run() {
        //create the person dynamically, eg based on some user input
        Person person = new Person("test");
    
        //new PersonService(person);
        //I used to create the object myself. now switching to spring.
        //how can I get the person object into the service using autowire?
    }
}

@Service
class PersonService {
    public PersonService(Person person) {
        this.person = person; //the object the service can work with
    }
}

Solution

  • You should annotate the costructor of your PersonService with @Autowired.

    @Service
    class PersonService {
        @Autowired
        public PersonService(Person person) {
            this.person = person; //the object the service can work with
        }
    }
    

    Then you must provide a Person bean somewhere.

    But I guess the Person is an instance that is loaded from a database. Since a PersonService is a singleton it makes no sense to bind it to one Person instance.

    In this case you have to create a new PersonService instance for every Person object that you retrieve from the db.

    If you want to do this then it also means that the PersonService is created by your code. Thus out of the spring containers control and therefore spring can not autowire it automatically.

    Nevertheless you can use the AutowireCapableBeanFactory to autowire beans that have been instantiated outside the container. But this is a one way. These beans will not be available to those defined in the container.

     AutowireCapableBeanFactory acbf = ...;
     acbf.autowireBean(someInstance);
    

    When I work with hibernate I usually use a PostLoadListener to autowire domain objects.

    But there is also another approach using aspectj and load-wime weaving. Take a look at the spring documentation 8.4.1

    If you need to advise objects not managed by the Spring container (such as domain objects typically), then you will need to use AspectJ. You will also need to use AspectJ if you wish to advise join points other than simple method executions (for example, field get or set join points, and so on).