Spring自动装配(autowire)篇

什么是自动装配

自动装配帮我们省去了 property标签配置操作,Spring会自动根据 属性名称,类型,构造器来进行自动注入。
例如不进行自动装配配置如下:

 <bean id="userDefault" class="cn.zhuoqianmingyue.ioc.di.autowire.UserDefault">
		<property name="country" ref="country"></property>
</bean>
<bean id="country" class="cn.zhuoqianmingyue.ioc.di.autowire.Country"></bean>

通过属性名称自动装配配置如下:

<bean id="userByName" class="cn.zhuoqianmingyue.ioc.di.autowire.UserByName" autowire="byName"></bean>
<bean id="country" class="cn.zhuoqianmingyue.ioc.di.autowire.Country"></bean>

自动装配类型

Spring自动装配分为4种:

1. default

default 不进行自动装配 默认采用 default。
配置方式如下:

    <bean autowire="default"></bean>

2. byName

通过名称进行自动装配。
配置方式如下:

    <bean autowire="byName"></bean>

3. byType

通过注入Bean的类类型来进行匹配。
配置方式如下:

   <bean autowire="byType"></bean>

4. constructor

通过构造器进行注入。
配置方式如下:

   <bean autowire="constructor"></bean>

需要注意的是在spring2.5 时候还有一种类型autowire=“autodetect” 它表示优先执行构造器的方式如果构造器没有就执行byType 不过在spring3.0的时候就废除了

自动装配的具体实现

1 默认方式:

spring xml配置文件配置如下:

  	<bean id="userDefault" class="cn.zhuoqianmingyue.ioc.di.autowire.UserDefault" autowire="default">
		<property name="country" ref="country"></property>
	</bean>
	<bean id="country" class="cn.zhuoqianmingyue.ioc.di.autowire.Country"></bean>

UserDefault类代码如下:

public class UserDefault {
	private Country country;

	public Country getCountry() {
		return country;
	}

	public void setCountry(Country country) {
		this.country = country;
	}
}

Country 类代码如下:

public class Country {
	private String name="CHINA";

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

进行测试:
测试类代码如下:

	@Test
	public void userDefault() {
		ApplicationContext appliction = new ClassPathXmlApplicationContext("ioc-di-autowire.xml");
		UserDefault user = (UserDefault)appliction.getBean("userDefault");
		System.out.println("country:"+user.getCountry().getName());
	}

测试结果:
在这里插入图片描述

必须为要注入成员属性设置set 方法并且set方法名称与注入的bean 名称一致

2 通过名称

spring xml配置文件配置如下:

<bean id="userByName" class="cn.zhuoqianmingyue.ioc.di.autowire.UserByName" autowire="byName">
</bean>
	<bean id="country" class="cn.zhuoqianmingyue.ioc.di.autowire.Country"></bean>

UserByName类 和 UserDefault 类内容一致
进行测试:
测试类代码如下:

	@Test
	public void userByName() {
		ApplicationContext appliction = new ClassPathXmlApplicationContext("ioc-di-autowire.xml");
		UserByName user = (UserByName)appliction.getBean("userByName");
		System.out.println("country:"+user.getCountry().getName());
	}

测试结果:
在这里插入图片描述

注入的成员属性必须有set方法 并且set方法名称与属性名称一样

3 通过类型

spring xml配置文件配置如下:

<bean id="userByType" class="cn.zhuoqianmingyue.ioc.di.autowire.UserByType" autowire="byType"></bean>
<bean class="cn.zhuoqianmingyue.ioc.di.autowire.Country"></bean>

UserByType 和 UserDefault 类内容一致
进行测试:
测试类代码如下:

	@Test
	public void userByType() {
		ApplicationContext appliction = new ClassPathXmlApplicationContext("ioc-di-autowire.xml");
		UserByType user = (UserByType)appliction.getBean("userByType");
		System.out.println("country:"+user.getCountry().getName());
	}

测试结果:
在这里插入图片描述

必须有set方法 但是set方法名称可以与属性名称不同

4 通过构造器

spring xml配置文件配置如下:

	 <bean id="userByConstructor" class="cn.zhuoqianmingyue.ioc.di.autowire.UserByConstructor" autowire="constructor"></bean>
	<bean  class="cn.zhuoqianmingyue.ioc.di.autowire.Country"></bean> 

UserByConstructor 具体代码如下:

public class UserByConstructor {
	private Country country;
	public UserByConstructor(Country country) {
		super();
		this.country = country;
	}
	public Country getCountry() {
		return country;
	}
}

进行测试:
测试类代码如下:

	@Test
	public void userByConstructor() {
		ApplicationContext appliction = new ClassPathXmlApplicationContext("ioc-di-autowire.xml");
		UserByConstructor user = (UserByConstructor)appliction.getBean("userByConstructor");
		System.out.println("country:"+user.getCountry().getName());
	}

测试结果:
在这里插入图片描述

constructor 的方式无需提供set方法

@Resource和@Autowired区别

  1. @Resource 通过 byName 方式自动装配
  2. @Autowired 通过ByType 方式自动装配
  3. @Autowired 和@Qualifier 可以实现ByName的效果
    如果Spring中有2个类型相同的Bean在通过@Autowired会报错 我们可以通过@Qualifier 标签来进行区分。

需要注意的是@Resource是javax.annotation包下的注解类 通过注解注入无需提供set方法

注解注入实战演示

1 @Resource

首先要创建我们演示的基础类:
ICountry接口类 方便创建多个Bean操作演示用

package cn.zhuoqianmingyue.ioc.di.autowire;

public interface ICountry {

	String getName();
}

CountryResource 类和CountryResource2 类都实现ICountry 表示同一类型的Bean

package cn.zhuoqianmingyue.ioc.di.autowire;

import org.springframework.stereotype.Component;

@Component
public class CountryResource implements ICountry{
	private String name="CountryResource";

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}
package cn.zhuoqianmingyue.ioc.di.autowire;

import org.springframework.stereotype.Component;

@Component
public class CountryResource2 implements ICountry{
	@Override
	public String getName() {
		return "CountryResource2";
	}
}

用户类 用于依赖CountryResource 类和CountryResource2 类

package cn.zhuoqianmingyue.ioc.di.autowire;

import javax.annotation.Resource;

import org.springframework.stereotype.Component;
@Component("userResource")
public class UserResource{
	@Resource(name="countryResource2")
	private ICountry countryResource;

	public ICountry getCountryResource() {
		return countryResource;
	}
}

测试类:

	@Test
	public void userResource() {
		ApplicationContext appliction = new ClassPathXmlApplicationContext("ioc-di-autowire.xml");
		UserResource user = (UserResource)appliction.getBean("userResource");
		System.out.println("country:"+user.getCountryResource().getName());
	}

测试结果:
在这里插入图片描述
根据上面案例结果是:没有配置Bean的名称会根据类名来进行自动装配
如果我们在@Component 标签指定名称 代码如下:

@Component("c1")
public class CountryResource implements ICountry{}
@Component("c2")
public class CountryResource2 implements ICountry{}

@Component("userResource")
public class UserResource{
	@Resource(name="c1")
	private ICountry countryResource;
}

测试结果:
在这里插入图片描述
指定Bean的名称 将按照指定名称进行自动装配
如果将name改成c3 我们没有配置任何名称为c3 的Bean

@Component("userResource")
public class UserResource{
	@Resource(name="c3")
}

会报如下错误:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named ‘c3’

如果Bean名称相同如下面代码示例:

@Component("c2")
public class CountryResource implements ICountry{}
@Component("c2")
public class CountryResource2 implements ICountry{}

会报如下错误:
org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from class path resource [ioc-di-autowire.xml]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name ‘c2’

2 @Autowired

创建CountryResource3 这里我们不实现ICountry接口

@Component
public class CountryResource3 {
	public String getName() {
		return "CountryResource3";
	}
}

创建名称为UserAutowired的Bean 然后注入 CountryResource3

@Component("userAutowired")
public class UserAutowired {
	@Autowired
	private CountryResource3 countryResource3;

	public CountryResource3 getCountryResource3() {
		return countryResource3;
	}
}

测试类代码:

	@Test
	public void userAutowired() {
		ApplicationContext appliction = new ClassPathXmlApplicationContext("ioc-di-autowire.xml");
		UserAutowired user = (UserAutowired)appliction.getBean("userAutowired");
		System.out.println("country:"+user.getCountryResource3().getName());
	}

测试结果:
在这里插入图片描述
我们将ICountry 接口注入UserAutowired Bean中
具体代码如下:

@Component("userAutowired")
public class UserAutowired {
	@Autowired
	private CountryResource3 countryResource3;
	@Autowired
	private ICountry countryResource;

	public ICountry getCountryResource() {
		return countryResource;
	}

	public CountryResource3 getCountryResource3() {
		return countryResource3;
	}
}

会报如下错误:

1WARN t.support.ClassPathXmlApplicationContext: 554 - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘userAutowired’: Unsatisfied dependency expressed through field ‘countryResource’; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type ‘cn.zhuoqianmingyue.ioc.di.autowire.ICountry’ available: expected single matching bean but found 2: c1,c2
这是我们需要通过@Qualifier标签来指定注入c1 还是c2
具体代码如下:

@Component("userAutowired")
public class UserAutowired {
	@Autowired
	private CountryResource3 countryResource3;
	@Autowired
	@Qualifier("c1")
	private ICountry countryResource;
}

测试代码:

	@Test
	public void userAutowired() {
		ApplicationContext appliction = new ClassPathXmlApplicationContext("ioc-di-autowire.xml");
		UserAutowired user = (UserAutowired)appliction.getBean("userAutowired");
		System.out.println("country:"+user.getCountryResource3().getName());
		System.out.println("country:"+user.getCountryResource().getName());
	}

测试结果:
在这里插入图片描述
Spring xml配置文件ioc-di-autowire.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"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
		http://www.springframework.org/schema/beans/spring-beans.xsd 
		http://www.springframework.org/schema/mvc 
		http://www.springframework.org/schema/mvc/spring-mvc.xsd 
		http://www.springframework.org/schema/context 
		http://www.springframework.org/schema/context/spring-context.xsd 
		http://www.springframework.org/schema/aop 
		http://www.springframework.org/schema/aop/spring-aop.xsd 
		http://www.springframework.org/schema/tx 
		http://www.springframework.org/schema/tx/spring-tx.xsd ">
<context:component-scan base-package="cn.zhuoqianmingyue"></context:component-scan>
	<!-- default -->
    	
  	<!--<bean id="userDefault" class="cn.zhuoqianmingyue.ioc.di.autowire.UserDefault" autowire="default">
		<property name="country" ref="country"></property>
	</bean>
	<bean id="country" class="cn.zhuoqianmingyue.ioc.di.autowire.Country"></bean>-->
	
	<!-- byName -->
 
	 <!-- <bean id="userByName" class="cn.zhuoqianmingyue.ioc.di.autowire.UserByName" autowire="byName"></bean>
	<bean id="country" class="cn.zhuoqianmingyue.ioc.di.autowire.Country"></bean>-->
	 <!-- byType -->
	<!-- <bean id="userByType" class="cn.zhuoqianmingyue.ioc.di.autowire.UserByType" autowire="byType"></bean>
	<bean  class="cn.zhuoqianmingyue.ioc.di.autowire.Country"></bean>  -->
	<!-- byConstructor -->
	 <bean id="userByConstructor" class="cn.zhuoqianmingyue.ioc.di.autowire.UserByConstructor" autowire="constructor"></bean>
	<bean  class="cn.zhuoqianmingyue.ioc.di.autowire.Country"></bean> 
	
	<!-- 这种方式spring3.0就废除掉了 -->
	<!-- 	
	<bean id="userByAutodetect" class="cn.zhuoqianmingyue.ioc.di.autowire.UserByConstructor" autowire="autodetect"></bean> 
    <bean  class="cn.zhuoqianmingyue.ioc.di.autowire.Country"></bean>
	-->
</beans>

查看源码
下载源码

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值