spring-ioc 核心之springbean的装配

spring-ioc装配

文章分文手动配置依赖(setter方法注入和构造函数注入)和byType及byName查找依赖

首先第一个手动配置依赖利用ClassPathXmlApplicationContext这个对象,非常普通的bean标签 setter方法注入和构造函数注入

	<bean id="dao1" class="org.springframework.test.main.dao.impl.UserDaoImpl1"></bean>
	<bean id="dao2" class="org.springframework.test.main.dao.impl.UserDaoImpl2"></bean>
	<bean id="service" class="org.springframework.test.main.service.impl.UserServiceImpl">
		<!-- service 依赖于 dao1-->
		<!-- setter 方法注入 name 属性为 setter方法名首字母小写 ref 属性为 注入到UserServiceImpl的<bean id='dao1'-->
		<!--<property name="dao11" ref="dao1"></property>-->
		<!-- 构造方法注入 name 为构造方法中注入的类型名称 ref 为注入属性类型的名称-->
		<constructor-arg name = "dao111" ref="dao1"></constructor-arg>
	</bean>
public class UserServiceImpl implements UserService {

	//setter 方法注入
//	UserDao dao1;
//	public void setDao11(UserDao dao1) {
//		this.dao1 = dao1;
//	}
	//构造 方法注入
	UserDao dao1;//注入属性类型名称
	public UserServiceImpl(UserDao dao111){//构造方法中注入属性的类型名称
		this.dao1 = dao111;
	}
	@Override
	public void query() {
		dao1.query();
		System.out.println("service");
	}
}

test测试

public class TestUserIoc {
	public static void main(String[] args) {
//ClassPathXmlApplicationContext cac = new ClassPathXmlApplicationContext("spring.xml");
//UserServiceImpl service = (UserServiceImpl) cac.getBean("service");
		AnnotationConfigApplicationContext cac = new AnnotationConfigApplicationContext(spring.class);
		UserServiceImpl service = (UserServiceImpl) cac.getBean("service");
		service.query();
	}
}

再来看byType 和 byName的装配方式

1.byName 已经注释掉依赖。byName的装配方式默认为为setter方法首字母小写,就是未设置name属性直接匹配id

<bean id="dao1" class="org.springframework.test.main.dao.impl.UserDaoImpl1"></bean>
	<bean id="dao2" class="org.springframework.test.main.dao.impl.UserDaoImpl2"></bean>
	<bean id="service" class="org.springframework.test.main.service.impl.UserServiceImpl" autowire="byName">
		<!-- service 依赖于 dao1-->
		<!-- setter 方法注入 name 属性为 setter方法名首字母小写 ref 属性为 注入到UserServiceImpl的<bean id='dao1'-->
		<!--<property name="dao" ref="dao1"></property>-->
		<!-- 构造方法注入 -->
		<!--<constructor-arg name="dao111"  ref="dao1"></constructor-arg>-->
	</bean>
public class UserServiceImpl implements UserService {

	//setter 方法注入
//	UserDao dao1;
//	public void setDao(UserDao dao1) {
//		this.dao1 = dao1;
//	}

	//构造 方法注入
//	UserDao dao1;
//	public UserServiceImpl(UserDao dao111){
//		this.dao1 = dao111;
//	}

	//byName 自动装配
	UserDao dao1;
	public void setDao1(UserDao dao1) {//setDao1首字母小写 可以改位setDao123 需和xml文件中bean id匹配,与此处的UserDao dao1 属性名无关,可以自己更改验证
		this.dao1 = dao1;
	}

	@Override
	public void query() {
		System.out.println("service");
		dao1.query();
	}
}

2.byType同样去掉依赖自动装配。byType是根据class的类型去装配的

	<bean id="dao1" class="org.springframework.test.main.dao.impl.UserDaoImpl1"></bean>
	<bean id="dao2" class="org.springframework.test.main.dao.impl.UserDaoImpl2"></bean>
	<bean id="service" class="org.springframework.test.main.service.impl.UserServiceImpl" autowire="byType">
		<!-- service 依赖于 dao1-->
		<!-- setter 方法注入 name 属性为 setter方法名首字母小写 ref 属性为 注入到UserServiceImpl的<bean id='dao1'-->
		<!--<property name="dao" ref="dao1"></property>-->
		<!-- 构造方法注入 -->
		<!--<constructor-arg name="dao111"  ref="dao1"></constructor-arg>-->
	</bean>
public class UserServiceImpl implements UserService {

	//setter 方法注入
//	UserDao dao1;
//	public void setDao(UserDao dao1) {
//		this.dao1 = dao1;
//	}

	//构造 方法注入
//	UserDao dao1;
//	public UserServiceImpl(UserDao dao111){
//		this.dao1 = dao111;
//	}

	//byName 自动装配
//	UserDao dao1;
//	public void setDao1(UserDao dao1) {
//		this.dao1 = dao1;
//	}

	//byType 自动装配
	UserDao  dao333;
	public void setDao444(UserDao dao333) {//根据class的类型去自动装配 可以发现这种装配方式与属性名无关与setter方法名无关
		this.dao333 = dao333;
	}

	@Override
	public void query() {
		System.out.println("service");
		dao333.query();
	}
}

我们可以测试一下是正常运行,但是如果将dao1和dao2类型这样改为同一个呢

	<bean id="dao1" class="org.springframework.test.main.dao.impl.UserDaoImpl1"></bean>
	<bean id="dao2" class="org.springframework.test.main.dao.impl.UserDaoImpl1"></bean>
	<bean id="service" class="org.springframework.test.main.service.impl.UserServiceImpl" autowire="byType">
		<!-- service 依赖于 dao1-->
		<!-- setter 方法注入 name 属性为 setter方法名首字母小写 ref 属性为 注入到UserServiceImpl的<bean id='dao1'-->
		<!--<property name="dao" ref="dao1"></property>-->
		<!-- 构造方法注入 -->
		<!--<constructor-arg name="dao111"  ref="dao1"></constructor-arg>-->
	</bean>

错误也很明显,我需要一个,但是匹配到了两个

除了改位byName以外,怎么样可以避免这类问题出现呢?下面结合了spring Annotation方式来验证

使用注解可以测试到@Autowired默认使用byType装配,@Resource默认使用byName(这儿的byName见下面解释)装配。到底是哪个注解次选byType装配后期验证

第一种组合注解使用指定一个具体的实现类

	//byType 自动装配
	@Autowired
	@Qualifier(value = "userDaoImpl1")
	UserDao dao;
	public void setDao(UserDao dao) {//根据class的类型去自动装配 可以发现这种装配方式与属性名无关与setter方法名无关
		this.dao = dao;
	}

第二种组合注解@Primary也指定一个具体的实现类

	//byType 自动装配
	@Autowired
	UserDao dao;
	public void setDao(UserDao dao) {//根据class的类型去自动装配 可以发现这种装配方式与属性名无关与setter方法名无关
		this.dao = dao;
	}

@Component
@Primary
public class UserDaoImpl2 implements UserDao {
	@Override
	public void query() {
		System.out.println("dao2");
	}
}

第三种使用@Resource注解,由上述代码运行后可以看到@Resource默认是使用byName,需要注意的是这个地方的byName的装配到的是属性名,与方法名无关。

	@Resource
	UserDao userDaoImpl1;
	public void setUserDaoImpl99999(UserDao dao) {//这儿默认是使用byName的装配方式,但这儿的byName匹配到的是属性名。与方法名无关
		this.userDaoImpl1 = dao;
	}

	@Override
	public void query() {
		System.out.println("service");
		userDaoImpl1.query();
	}

下面这种运行可以得到如果注解中有属性值,则以注解内的值为准,打印为dao2

	@Resource(name = "userDaoImpl2")
	UserDao userDaoImpl1;
	public void setUserDaoImpl99999(UserDao dao) {//这儿默认是使用byName的装配方式,但这儿的byName匹配到的是属性名。与方法名无关
	this.userDaoImpl1 = dao;
	}

	@Override
	public void query() {
		System.out.println("service");
		userDaoImpl1.query();
	}

接下来看看@Resource注解的type属性,我们如果按照下面的装配形式运行,肯定是会报错的。要么将@Resource(type = UserDaoImpl2.class)改为@Resource(type = UserDaoImpl1.class) 或者将UserDao userDaoImpl1改为UserDao userDaoImpl2一一对应即可成功。所以综上所述@Resource装配是类型默认以byName。但是这儿的byName又是以属性名装配的。

	@Resource(type = UserDaoImpl2.class)
	UserDao userDaoImpl1;
	public void setUserDaoImpl99999(UserDao dao) {//这儿默认是使用byName的装配方式,但这儿的byName匹配到的是属性名。与方法名无关
	this.userDaoImpl1 = dao;
	}

	@Override
	public void query() {
		System.out.println("service");
		userDaoImpl1.query();
	}

下篇请看代码解析ioc的装配

猜你喜欢

转载自blog.csdn.net/qq_38108719/article/details/99674379