1. 9IM首页
  2. 热点

Spring大神之路(10)–详解Spring中bean命名机制

概述

上一篇已经对bean命名的重要性进行了说明,本篇主要讲解下bean命名的具体实现方式,同时还会实验下如果出现重复命名,Spring会如何处理。

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

注解配置中bean命名

可以使用@Component("beanName")将类生成的bean命名为beanName,如果直接使用@Component,则采用类名首字母小写的形式作为生成bean的名称。

例如:

@Component("zhoujielun")//生成bean的名称为zhoujielun
public class Singer {
}
@Component//生成bean的名称为singer,即类名首字母小写
public class Singer {
}

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();
	}
}

正常输出:

歌手[周杰伦]开唱啦,快挥舞起你手中的荧光棒吧
歌手[林俊杰]开唱啦,快挥舞起你手中的荧光棒吧

此时,如果我们配置两个同名的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了。

总结

在正常开发过程,还是要遵循每个bean名称都要有唯一名称的原则,即便同时采用了多种配置方式,也要为每个bean采用单独名称。

毕竟,虽然配置方式不同,但是生成的bean都是在Spring容器中一样管理的。

原创文章,作者:9IM,如若转载,请注明出处:https://www.9im.cn/892.html

发表评论

电子邮件地址不会被公开。 必填项已用*标注