1

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
    }
}

3 Answers 3

2

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).

Sign up to request clarification or add additional context in comments.

2 Comments

How would I provide that person bean? This would probably have to be some kind of "static" person? I'm rather looking into creating a dynamic person and then processing it with PersonService...
@membersound I would recommend to make the PersonService stateless. I mean that it should not be dependent on a Person instance. Then pass the person to each method call.
0

Make a person a @Component and add @ConstructorProperties to the constructor

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

Comments

0

Just add an empty constructor above the other

@Service
class PersonService {

 public PersonService() {

        }

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

 //Getters and setters

}

Then keep other class and if you want to call the person

1 Comment

OK that would work, but then it is not guaranteed anymore that a person object has been set into the service, probably causing null pointer exceptions. That's why I forced to set the service with required person object in constructor...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.