1. 概述
上一篇已经对bean命名的重要性进行了说明,本篇主要讲解下bean命名的具体实现方式,同时还会实验下如果出现重复命名,Spring会如何处理。
2. xml配置中bean命名
首先有一个歌手类:
package org.maoge.xmlbeandetail;
public class Singer {
private String name;
public void sing() {
System.out.println("歌手[" + name + "]开唱啦,快挥舞起你手中的荧光棒吧");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
在xml中对bean进行正常命名,给两个bean分别命名为zhoujielun、linjunjie。
<?xml version="1.0" encoding="UTF-8"?><!-- spring.xml文件 -->
<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 id="zhoujielun" class="org.maoge.xmlbeandetail.Singer">
<property name="name" value="周杰伦"></property>
</bean>
<bean id="linjunjie" class="org.maoge.xmlbeandetail.Singer">
<property name="name" value="林俊杰"></property>
</bean>
</beans>
在主类中,首先获取容器,然后通过命名获取容器中的bean:
package org.maoge.xmlbeandetail;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
"/org/maoge/xmlbeandetail/spring.xml");
// 杰伦来了
Singer zhoujielun = context.getBean("zhoujielun", Singer.class);
zhoujielun.sing();
// 俊杰来了
Singer linjunjie = context.getBean("linjunjie", Singer.class);
linjunjie.sing();
}
}
执行结果:
歌手[周杰伦]开唱啦,快挥舞起你手中的荧光棒吧
歌手[林俊杰]开唱啦,快挥舞起你手中的荧光棒吧
此时如果修改spring.xml文件,在其中命名两个重名的bean,如下:
<?xml version="1.0" encoding="UTF-8"?><!-- spring.xml文件 -->
<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 id="zhoujielun" class="org.maoge.xmlbeandetail.Singer">
<property name="name" value="周杰伦"></property>
</bean>
<bean id="zhoujielun" class="org.maoge.xmlbeandetail.Singer">
<property name="name" value="林俊杰"></property>
</bean>
</beans>
执行Main.java主类时,控制台报错,提示名称为zhoujielun的bean已经存在了,所以在同一xml配置中,Spring是不允许出现同名bean的。
Exception in thread "main" org.springframework.beans.factory.parsing.BeanDefinitionParsingException:
Configuration problem: Bean name 'zhoujielun' is already used in this <beans> element
3. 注解配置中bean命名
可以使用@Component("beanName")将类生成的bean命名为beanName,如果直接使用@Component,则采用类名首字母小写的形式作为生成bean的名称。
例如:
@Component("zhoujielun")//生成bean的名称为zhoujielun
public class Singer {
}
@Component//生成bean的名称为singer,即类名首字母小写
public class Singer {
}
4. JavaConfig配置中bean命名
使用@Bean标注到方法上,方法的名称即为生成bean的名称,如下:
package org.maoge.javaconfigbean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class BeanConfiguration {
@Bean//生成bean名称为zhoujielun
public Singer zhoujielun() {
Singer singer = new Singer();
singer.setName("周杰伦");
return singer;
}
@Bean//生成bean名称为linjunjie
public Singer linjunjie() {
Singer singer = new Singer();
singer.setName("林俊杰");
return singer;
}
}
运行主类:
package org.maoge.javaconfigbean;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class JavaConfigContainerDemo {
public static void main(String[] args) {
AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(BeanConfiguration.class);
Singer zhoujielun=(Singer) context.getBean("zhoujielun");
zhoujielun.sing();
Singer linjunjie=(Singer) context.getBean("linjunjie");
linjunjie.sing();
}
}
正常输出:
歌手[周杰伦]开唱啦,快挥舞起你手中的荧光棒吧
歌手[林俊杰]开唱啦,快挥舞起你手中的荧光棒吧
1
2
此时,如果我们配置两个同名的bean,强制将两个bean都命名为zhoujielun,如下:
package org.maoge.javaconfigbean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class BeanConfiguration {
@Bean(name= {"zhoujielun"})//强制将bean命名为zhoujielun
public Singer zhoujielun() {
Singer singer = new Singer();
singer.setName("周杰伦");
return singer;
}
@Bean(name= {"zhoujielun"})//强制将bean命名为zhoujielun
public Singer linjunjie() {
Singer singer = new Singer();
singer.setName("林俊杰");
return singer;
}
}
再次运行主类,控制台输出如下:
歌手[周杰伦]开唱啦,快挥舞起你手中的荧光棒吧
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'linjunjie' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:682)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1218)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:284)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1082)
at org.maoge.javaconfigbean.JavaConfigContainerDemo.main(JavaConfigContainerDemo.java:8)
首先我们发现如果@Configuration配置类中有重名的bean,第一个会覆盖后面的,也就是说第一个生效。后面报错是因为没有名字为linjunjie的bean了,因为第二个bean已经通过@Bean(name= {"zhoujielun"})强制命名为zhoujielun了。
5. 总结
在正常开发过程,还是要遵循每个bean名称都要有唯一名称的原则,即便同时采用了多种配置方式,也要为每个bean采用单独名称。
毕竟,虽然配置方式不同,但是生成的bean都是在Spring容器中一样管理的。