I'm still learning spring dependency injection in depth.
My first class is a configuration class, where i declare to the container to load and manage the beans declared in the annotated methods.
package ioc.question_004;
import ioc.commun.Person;
import ioc.commun.Profession;
import org.springframework.context.annotation.*;
@Configuration
public class MyConfiguration {
@Bean
public Profession profession(){
return Profession.builder()
.name("professor")
.description("professor in the university")
.build();
}
@Bean
public Person person(){
return Person.builder()
.name("Bagna")
.age(52)
.profession(profession())
.build();
}
}
My second class is a daoRepository, it looks likes:
package ioc.question_008.dao;
import ioc.commun.Person;
import lombok.*;
import org.springframework.stereotype.Repository;
import java.util.ArrayList;
import java.util.List;
@Repository
@Builder
@Setter
@Getter
@EqualsAndHashCode
@ToString
public class MyDaoRepository implements dao {
List<Person> personList = new ArrayList<>();
@Override
public boolean save( Person person ){
return this.personList.add(person);
}
@Override
public boolean delete( Person person ){
return this.personList.remove(person);
}
}
My running code is as follows:
@Configuration
@Import(MyConfiguration.class)
@ComponentScan(basePackageClasses = {MyDaoRepository.class} )
public class DependencyInjection {
public static void main( String[] args ) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DependencyInjection.class);
dao myDaoRepository = (MyDaoRepository) context.getBean("myDaoRepository");
System.out.println(myDaoRepository);
}
}
Magically MyDaoRepository contains the @Bean person declared in the configuration class MyConfiguration:
MyDaoRepository(personList=[Person(name=Bagna, age=52, profession=Profession(name=professor, description=professor in the university))])
I thnik that the container injected this object automatically even if i didn't ask for that. May be some @Autowired annotation is added by the compiler. I'm not sure.
Could you please explain to me how i can ask the spring container to not inject the beans even if they exists in the container(the bean person for example), unless i ask the to do the injection by myself with the @Autowired annotation.
The reason is the combination of spring's autowiring of collections and lombok's Builder
First, the @Builder
adds an all args constructor MyDaoRepository(List<Person> list)
.
Second, spring automatically detects your factory methods @Bean public Person person()
.
Now, since the constructor expects a collection, spring accumulates all Person
-beans it can find into a List
and injects it into the constructor, setting the list accordingly.
I think (but it is currently untested but documented here), that adding @Autowired(required = false)
to your List<Person> persons
property is what you want in this case, as that marks it as optional and spring will not inject it. (EDIT: I was mistaken, you still need the no-args-constructor for this to work, but without any @Autowired
annotation the list would not get injected that way anyway. The required=false
simply prevents the exception when no proper Person
bean is found.)
EDIT: As Mr. Roddy, the Roddy of the Frozen Peas, pointed out, it would also be possible to add a different constructor for spring to create your bean, e.g. by annotating your repository with @NoArgsConstructor