There are 2 aspects here to be covered, so let's take them one at a time:
1)IJ (short for IntelliJ Idea) is suggesting that according to your bean declaration, Spring will be trying to invoke a no-arg constructor, which clearly does not exist since you've defined public Auditorium(String name, Integer numberOfSeats, List<String> vipSeats)
.
Thus you can configure it to call the above mentioned constructor passing the correct arguments, as per the spring docs:
<bean class="com.example.Auditorium">
<constructor-arg name="name" value="${auditorium1.name}"/>
<constructor-arg name="numberOfSeats" value="${auditorium1.number-of-seats}"/>
<constructor-arg name="vipSeats" value="${auditorium1.vip-seats}"/>
</bean>
Apart from this, no special handling is required for Spring to inject your list, as you can see in the log snippet below, outputted by a simple toString()
IJ auto-generated method:
16:13:56.569 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'com.example.Auditorium#0'
16:13:56.601 [main] DEBUG com.example.Auditorium - Auditorium{id=null, name='yellow hall', numberOfSeats=150, vipSeats=[1,2,3,4,5,6,7,8,9]}
2) I see you're trying to use the p-namespace to pass arguments to your constructor, however that's used to set properties/attribute after bean instantiation. You can use the c-namespace to achieve the same effect as using the <constructor-arg>
tag and be less verbose (please note that as per the spring docs, p & c namespaces the are not defined in an XSD file and exist only in the core of Spring):
<beans ...
xmlns:c="http://www.springframework.org/schema/c"
...>
<bean id="myAuditorium" class="com.example.Auditorium" c:name="${auditorium1.name}" c:numberOfSeats="${auditorium1.number-of-seats}" c:vipSeats="${auditorium1.vip-seats}"/>
And again the log snippet, generated for both the definitions this time:
16:26:52.258 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'com.example.Auditorium#0'
16:26:52.287 [main] DEBUG com.example.Auditorium - Auditorium{id=null, name='yellow hall', numberOfSeats=150, vipSeats=[1,2,3,4,5,6,7,8,9]}
...
16:26:52.287 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'com.example.Auditorium#1'
16:26:52.288 [main] DEBUG com.example.Auditorium - Auditorium{id=null, name='yellow hall', numberOfSeats=150, vipSeats=[1,2,3,4,5,6,7,8,9]}
Note: Depending on the Spring version that you are using & your needs, it may be worth also checking
annotation-based configs. It may be a personal preference, but I find them cleaner and easier to maintain, and IJ has excellent Spring support for both types of config.
Special request update: Brief annotation introduction
First of all it depends on your project's setup, whether you use basic Spring Core or Spring Boot as well, etc. For this introduction: I'll just start from where you are at this point:
Enable component scanning so Spring can discover and create your components, services, etc
<?xml version="1.0" encoding="UTF-8"?>
<beans ...
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="...
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.example" />
Then change our class. If you don't need to do anything else in your constructor then we can simply remove it and annotate the fields. When annotating fields please take into consideration that Spring will be able to populate them only after instantiating the beans, hence using then in a constructor will most likly result in a NPE. In such cases you can use @PostConstruct
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class Auditorium {
private static final Logger log = LoggerFactory.getLogger(Auditorium.class);
private Integer id;
@Value("${auditorium1.name}")
private String name;
@Value("${auditorium1.number-of-seats}")
private Integer numberOfSeats;
@Value("${auditorium1.vip-seats}")
private List<String> vipSeats;
@PostConstruct
private void doAfterConstruction() {
log.debug(this.toString());
}
@Override
public String toString() {
return "Auditorium{" +
"id=" + id +
", name='" + name + '\'' +
", numberOfSeats=" + numberOfSeats +
", vipSeats=" + vipSeats +
'}';
}
}
As you'll see in the log, Spring will instantiate the bean, then inject the values for its fields and eventually the post-processors will call the @PostConstruct
annotated method:
12:20:34.037 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating shared instance of singleton bean 'auditorium'
12:20:34.038 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'auditorium'
12:20:34.045 [main] DEBUG o.s.c.a.CommonAnnotationBeanPostProcessor - Found init method on class [com.example.Auditorium]: private void com.example.Auditorium.doAfterConstruction()
12:20:34.045 [main] DEBUG o.s.c.a.CommonAnnotationBeanPostProcessor - Registered init method on class [com.example.Auditorium]: org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement@1ec4fbf0
12:20:34.060 [main] DEBUG o.s.b.f.annotation.InjectionMetadata - Registered injected element on class [com.example.Auditorium]: AutowiredFieldElement for private java.lang.String com.example.Auditorium.name
12:20:34.060 [main] DEBUG o.s.b.f.annotation.InjectionMetadata - Registered injected element on class [com.example.Auditorium]: AutowiredFieldElement for private java.lang.Integer com.example.Auditorium.numberOfSeats
12:20:34.060 [main] DEBUG o.s.b.f.annotation.InjectionMetadata - Registered injected element on class [com.example.Auditorium]: AutowiredFieldElement for private java.util.List com.example.Auditorium.vipSeats
12:20:34.060 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Eagerly caching bean 'auditorium' to allow for resolving potential circular references
12:20:34.062 [main] DEBUG o.s.b.f.annotation.InjectionMetadata - Processing injected element of bean 'auditorium': AutowiredFieldElement for private java.lang.String com.example.Auditorium.name
12:20:34.067 [main] DEBUG o.s.b.f.annotation.InjectionMetadata - Processing injected element of bean 'auditorium': AutowiredFieldElement for private java.lang.Integer com.example.Auditorium.numberOfSeats
12:20:34.072 [main] DEBUG o.s.b.f.annotation.InjectionMetadata - Processing injected element of bean 'auditorium': AutowiredFieldElement for private java.util.List com.example.Auditorium.vipSeats
12:20:34.084 [main] DEBUG o.s.c.a.CommonAnnotationBeanPostProcessor - Invoking init method on bean 'auditorium': private void com.example.Auditorium.doAfterConstruction()
12:20:34.085 [main] DEBUG com.example.Auditorium - Auditorium{id=null, name='yellow hall', numberOfSeats=150, vipSeats=[1,2,3,4,5,6,7,8,9]}
12:20:34.094 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'auditorium'
Or if you'd like to keep your constructor, we'll just mark it as @Autowired
and annotate the parameters as well:
@Component
public class Auditorium {
private static final Logger log = LoggerFactory.getLogger(Auditorium.class);
private Integer id;
private String name;
private Integer numberOfSeats;
private List<String> vipSeats;
@Autowired
public Auditorium(@Value("${auditorium1.name}") String name,
@Value("${auditorium1.number-of-seats}") Integer numberOfSeats,
@Value("${auditorium1.vip-seats}") List<String> vipSeats) {
this.name = name;
this.numberOfSeats = numberOfSeats;
this.vipSeats = vipSeats;
log.debug(this.toString());
}
}
And the log, which is simpler this time
12:29:09.492 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating shared instance of singleton bean 'auditorium'
12:29:09.492 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'auditorium'
12:29:09.525 [main] DEBUG com.example.Auditorium - Auditorium{id=null, name='yellow hall', numberOfSeats=150, vipSeats=[1,2,3,4,5,6,7,8,9]}
12:29:09.526 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Eagerly caching bean 'auditorium' to allow for resolving potential circular references
12:29:09.548 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'auditorium'