Java web项目创建笔记7 之《springmvc基础配置——byName和byType》

在beans标签中,有一个配置,那他们有什么区别?
default-autowire="byName"

default-autowire="byType"

一、byName是什么
byName就是用我们定义的bean的id或name(可看上一篇id和name的区别)来匹配
bean的name有且只有一个,aliases可以有多个
并且bean的name不能重复

二、byType是什么
byType就是使用类的类类型来匹配

这个有些像通过ApplicationContext对象的getBean()方法,一种是传String name,一种是传Class<T> requiredType

三、测试byName
1、applicationContext.xml增加配置
beans标签增加default-autowire="byName"
声明两个测试bean,id为“id.student1”和“id.student2”

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.3.xsd" 
        default-autowire="byName">

	<!-- 注解bean扫描,spring扫描排除Controller -->
	<context:annotation-config />
	<context:component-scan base-package="com.study">
		<context:exclude-filter type="annotation"
			expression="org.springframework.stereotype.Controller" />
	</context:component-scan>

	<!-- 下面可以导入其他spring配置文件 -->
	<import resource="classpath:/spring-env.xml" />

	<!-- 下面可以声明bean -->
	<bean id="id.student1" name="name.student1" class="com.study.testBean.Student">
		<property name="name" value="小明"></property>
		<property name="age" value="12"></property>
	</bean>
	<bean id="id.student2" name="name.student2" class="com.study.testBean.Student">
		<property name="name" value="小李"></property>
		<property name="age" value="33"></property>
	</bean>
</beans>

2、MyTest.java测试类增加注入对象和测试方法

package webapp;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;

import com.study.testBean.Student;
import com.study.util.ApplicationContextHolder;
import com.study.util.PropertiesUtil;
import com.study.util.ReflectInvokeUtil;

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = {"classpath:applicationContext.xml","classpath:spring-mvc.xml"})
@ActiveProfiles("sit")
public class MyTest {

	@Value("${flag}")
	String flag;
	
	@Autowired
	Student stu;
	
	@Test
	public void testInvoke() throws Exception {
		System.out.println("第一个测试方法*******");
		ApplicationContext ac = ApplicationContextHolder.getApplicationContext();
		ReflectInvokeUtil.invokeMethod("com.study.testBean.Student", "sayHello", null);
	}
	
	@Test
	public void testById() {
		System.out.println("第二个测试方法*******");
		ApplicationContext ac = ApplicationContextHolder.getApplicationContext();
		Student stu = (Student)ApplicationContextHolder.getBean("id.student1");
		stu.sayHello();
		System.out.println("**********");
	}
	
	@Test
	public void testProperties() {
		System.out.println("第三个测试方法*******");
		System.out.println("flag is:" + flag);
		System.out.println("appName is:" + PropertiesUtil.getProperties("appName"));
	}
	
	@Test
	public void testAutowired() {
		System.out.println("第四个测试方法*******");
		stu.sayHello();
		System.out.println("**********");
	}
}

3、执行testAutowired方法
日志报错:

11:52:01.642 [main] ERROR org.springframework.test.context.TestContextManager - Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener@55f3ddb1] to prepare test instance [webapp.MyTest@14bdbc74]
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'webapp.MyTest': Unsatisfied dependency expressed through field 'stu'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.study.testBean.Student' available: expected single matching bean but found 2: id.student1,id.student2
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:586)
	at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:364)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1269)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:384)
	at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:118)
	at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
	at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.study.testBean.Student' available: expected single matching bean but found 2: id.student1,id.student2
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveNotUnique(DependencyDescriptor.java:173)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1114)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:583)
	... 28 common frames omitted

错误信息为:
No qualifying bean of type 'com.study.testBean.Student' available: expected single matching bean but found 2: id.student1,id.student2
原因:没有匹配到类型com.study.testBean.Student,在spring的context里找到两个相同类型的bean:id.student1和id.student2
疑问:是否Autowired默认使用按类型装配?

4、将id.student2定义注释掉,再次执行testAutowired,这时执行成功:
相关日志:

...
15:52:54.230 [main] DEBUG org.springframework.beans.factory.annotation.InjectionMetadata - Processing injected element of bean 'webapp.MyTest': AutowiredFieldElement for com.study.testBean.Student webapp.MyTest.stu
15:52:54.231 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'id.student1'
15:52:54.231 [main] DEBUG org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor - Autowiring by type from bean name 'webapp.MyTest' to bean named 'id.student1'
15:52:54.233 [main] DEBUG org.springframework.test.context.support.AbstractDirtiesContextTestExecutionListener - Before test method: context [DefaultTestContext@7cd62f43 testClass = MyTest, testInstance = webapp.MyTest@14bdbc74, testMethod = testAutowired@MyTest, testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@6d4b1c02 testClass = MyTest, locations = '{classpath:applicationContext.xml, classpath:spring-mvc.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{sit}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextCustomizers = set[[empty]], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.test.context.web.WebDelegatingSmartContextLoader', parent = [null]]], class annotated with @DirtiesContext [false] with mode [null], method annotated with @DirtiesContext [false] with mode [null].
第四个测试方法*******
student say hello. name=小明 age=12
**********
...

5、如何使用指定的名字注入
使用@Qualifier注解指定bean的名字
@Autowired
@Qualifier("id.student2")
Student stu;

再次执行testAutowired,这时执行成功:

相关日志:

...
16:19:57.195 [main] DEBUG org.springframework.beans.factory.annotation.InjectionMetadata - Processing injected element of bean 'webapp.MyTest': AutowiredFieldElement for com.study.testBean.Student webapp.MyTest.stu
16:19:57.196 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'id.student2'
16:19:57.196 [main] DEBUG org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor - Autowiring by type from bean name 'webapp.MyTest' to bean named 'id.student2'
16:19:57.198 [main] DEBUG org.springframework.test.context.support.AbstractDirtiesContextTestExecutionListener - Before test method: context [DefaultTestContext@4883b407 testClass = MyTest, testInstance = webapp.MyTest@12591ac8, testMethod = testAutowired@MyTest, testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@7d9d1a19 testClass = MyTest, locations = '{classpath:applicationContext.xml, classpath:spring-mvc.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{sit}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextCustomizers = set[[empty]], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.test.context.web.WebDelegatingSmartContextLoader', parent = [null]]], class annotated with @DirtiesContext [false] with mode [null], method annotated with @DirtiesContext [false] with mode [null].
第四个测试方法*******
student say hello. name=小李 age=33
**********
...

四、测试byType
修改为default-autowire="byType"
重新测试2、3、4、5,结果和byName一致
疑问;是否default-autowire对@Autowired注解没有效果?

小结:
1)@Autowired注解默认按照byType类型装配
2)byType默认使用类的全限定名查找
3)如果需要指定byName,使用@Qualifier注解

五、例子程序
webapp_1.rar
链接: https://pan.baidu.com/s/15sJUYamn6qc8KcFEQXmiiA 提取码: xnjn

参考资料:
http://www.importnew.com/27815.html
https://www.cnblogs.com/think-in-java/p/5474740.html
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值