Reputation: 703
I want to reference a java config class in my Spring config xml file, but failed, please see below my code:
Bean1 class :
package c2_5_2.ref.javaconfig.from.xml;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component("bean1")
public class Bean1 {
@Autowired
public Bean1(Bean2 bean2)
{
this.bean2 = bean2;
}
private Bean2 bean2;
public Bean2 getBean2() {
return bean2;
}
}
Bean2 class :
package c2_5_2.ref.javaconfig.from.xml;
import java.util.List;
public class Bean2 {
private List<String> nameList;
public List<String> getNameList() {
return nameList;
}
public void setNameList(List<String> nameList) {
this.nameList = nameList;
}
public void displayNames()
{
for(String name : nameList)
{
System.out.println(name);
}
}
}
Bean3 Class :
package c2_5_2.ref.javaconfig.from.xml;
public class Bean3 {
private Bean1 b1;
public Bean1 getB1() {
return b1;
}
public void setB1(Bean1 b1) {
this.b1 = b1;
}
public void introduce()
{
System.out.println("this is bean 3");
}
}
Java Config Class :
package c2_5_2.ref.javaconfig.from.xml;
import java.util.ArrayList;
import java.util.List;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages= {"c2_5_2.ref.javaconfig.from.xml"})
public class BeanConfig {
@Bean(name="bean2")
public Bean2 getBean2()
{
Bean2 b2 = new Bean2();
List<String> nameList = new ArrayList<String>();
nameList.add("Bitt");
nameList.add("Rock");
nameList.add("Lucas");
nameList.add("Crius");
b2.setNameList(nameList);
return b2;
}
}
BeanConfig.xml :
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="c2_5_2.ref.javaconfig.from.xml.BeanConfig"></bean>
<bean id="bean3" class="c2_5_2.ref.javaconfig.from.xml.Bean3"></bean>
</beans>
Run Test method :
private static void test3()
{
ApplicationContext ctx = new ClassPathXmlApplicationContext("c2_5_2/ref/javaconfig/from/xml/BeanConfig.xml");
Bean3 b3 = ctx.getBean(Bean3.class);
b3.introduce();
Bean1 b1 = ctx.getBean(Bean1.class);
}
Get following output and error message:
Oct 13, 2017 9:55:16 AM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@6d9c638: startup date [Fri Oct 13 09:55:16 CST 2017]; root of context hierarchy
Oct 13, 2017 9:55:16 AM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [c2_5_2/ref/javaconfig/from/xml/BeanConfig.xml]
**this is bean 3**
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'c2_5_2.ref.javaconfig.from.xml.Bean1' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:348)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:335)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1101)
at c2_5_2.ref.javaconfig.from.xml.Test_Driven.test3(Test_Driven.java:33)
at c2_5_2.ref.javaconfig.from.xml.Test_Driven.main(Test_Driven.java:12)
So from the output we can see the spring configuration xml file is found by spring framework because we got output "This is bean 3", but other 2 beans, "bean1" and "bean2" cannot be found even though I put the qualified name of BeanConfig class as a value to class property of the bean element in BeanConfig.xml file.
My concern is why spring cannot find the Bean definition, how to fix it?
Upvotes: 0
Views: 881
Reputation: 1527
if you use xml as config file to load the context you need to add <context:component-scan base-package="c2_5_2.ref.javaconfig.from.xml" />
which will fix your problem. since you code just create the BeanConfig class as a bean but it doesn't know that it is a configuration and trigger the scan the package. because you just create a bean.
once you add context-scan-package in ur xml, it will scan and get the BeanConfig file as config class which will create the bean2 and scan the package (redundant package)
Via component scanning
@Configuration is meta-annotated with @Component, therefore @Configuration classes are candidates for component scanning (typically using Spring XML's element) and therefore may also take advantage of @Autowired/@Inject like any regular @Component. In particular, if a single constructor is present autowiring semantics will be applied transparently:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="c2_5_2.ref.javaconfig.from.xml.BeanConfig"></bean>
<bean id="bean3" class="c2_5_2.ref.javaconfig.from.xml.Bean3"></bean>
<context:component-scan base-package="c2_5_2.ref.javaconfig.from.xml" />
</beans>
update: if you want to create the bean as configuration file you can do:
Via Spring XML
<beans>
<context:annotation-config/>
<bean class="c2_5_2.ref.javaconfig.from.xml.BeanConfig"/>
</beans>
see detail : how spring look for @Configuration
Upvotes: 1