自动装配 @Autowired @Resource
自动装配 @Autowired @Resource
基于注解配置bean,也可以实现自动装配,使用的注解是@Autowired @Resource
- @Component 标识该类是一个组件, 是一个通用的注解
- @Controller 标识该类是一个控制器Controller, 通常这个类是一个Servlet
- @Repository 标识该类是一个Repository是一个持久化层的类/对象
- @Service 标识该类是一个Service类/对象
@Autowired
1)在IOC容器中查找待装配的组件的类型,如果有唯一的bean匹配(按照类型),则使用该bean装配
2)如待装配的类型对应的bean在IOC容器中有多个,则使用待装配的属性的属性名作为id值再进行查找, 找到就装配,找不到就抛异常
@Resource
@Resource有两个属性是比较重要的,分是name和type,
<1>Spring将@Resource注解的name属性解析为bean的名字,所以如果使用name属性,@Resource(name = “userService”) 表示装配 id=userService对象.<2> >type属性则解析为bean的类型.使用type属性时则使用byType自动注 入策略.比如 @Resource(type = UserService.class) 表示按照UserService.class类型进行装配, 这时要求容器中,只能有一个这样类型的对象
如果@Resource 没有指定 name 和 type ,则先使用byName注入策略, 如果匹配不上, 再使用byType策略, 如果都不成功,就会报错
1.src目录下写配置文件beans.xml,
此时此刻在beans.xml 这个配置文件对应的容器中有3个userService,一个是基于注解扫描的形式加进去的,(也就是userService.java里注解@Service). userService200, userService300
<?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
https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan
base-package="com.elf.spring.component"/>
<!--配置两个UserService对象-->
<bean class="com.elf.spring.component.UserService" id="userService200"/>
<bean class="com.elf.spring.component.UserService" id="userService300"/>
</beans>
2.UserService类
package com.elf.spring.component;
import org.springframework.stereotype.Service;
/**
* @author 90
* @version 1.0
* @Service 标识该类是一个Service类/对象
*/
@Service
public class UserService {
//方法..
public void hi(){
System.out.println("UserService hi()~");
}
}
3.UserDao类
package com.elf.spring.component;
import org.springframework.stereotype.Repository;
/**
* @author 45
* @version 1.0
* 使用 @Repository 标识该类是一个Repository是一个持久化层的类/对象
* 1. 标记注解后,类名首字母小写作为id的值(默认)
* 2. value = "elfUserDao" 使用指定的 elfUserDao作为UserDao对象的id
*/
@Repository/*(value = "elfUserDao")*/
public class UserDao {
}
4.MyComponent类
package com.elf.spring.component;
import org.springframework.stereotype.Component;
/**
* @author 45
* @version 1.0
* @Component 标识该类是一个组件, 是一个通用的注解
*/
@Component(value = "elf1")
public class MyComponent {
}
5.AutoTest 测试类
package com.elf.spring.test;
import com.elf.spring.component.UserAction;
import com.elf.spring.component.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author 45~
* @version 1.0
*/
public class AutoTest {
//通过注解来配置Bean
@Test
public void setProByAutowired() {
ApplicationContext ioc =
new ClassPathXmlApplicationContext("beans06.xml");
UserService userService = ioc.getBean("userService", UserService.class);
System.out.println("ioc容器中的userService=" + userService);
userService.hi();
UserService userService200 = ioc.getBean("userService200", UserService.class);
System.out.println("ioc容器中的userService200=" + userService200);
UserAction userAction = ioc.getBean("userAction", UserAction.class);
// //System.out.println("userAction=" + userAction);
userAction.sayOk();
//
// UserService userService300 = ioc.getBean("userService300", UserService.class);
// System.out.println("ioc容器中的userService300=" + userService300);
//
// System.out.println("userService=" + userService);
// System.out.println("userService200=" + userService200);
// System.out.println("userService300=" + userService300);
}
}
- UserAction 类
package com.elf.spring.component;
import org.springframework.stereotype.Controller;
import javax.annotation.Resource;
/**
* @author 45
* @version 1.0
* @Controller 标识该类是一个控制器Controller, 通常这个类是一个Servlet
*/
@Controller
public class UserAction {
//xml配置 ref
//@Autowired
//说明: @Autowired + @Qualifier(value = "userService02") 组合也可以完成指定 name/id 来进行自动装配
//指定id进行组装, 也可以使用@Autowired 和 @Qualifier(value = "userService02")
// 这时,是装配的 id=userService02 , 需要两个注解都需要写上
/** @Autowired 若这里注解为 @Autowired,属性名写userService400:
需要注销配置文件里200和300,只留注解扫描包那个就会成功
此时是按唯一bean,类型来做的,至于名字叫什么无所谓!!!
此时唯一能注入的就是通过注解默认到类名首字母小写的bean
**/
/**
* @Resource(name = "userService200")
* /**这里由于@Resource已经指定了id,把名字为userService的对象注入/装配到属性上
* 至于下面的属性名称为userService600或者别的什么已经没有意义了不考虑
*/
@Resource(name = "userService200")
//@Resource(type = UserService.class)//这是要求容器中只能由一个这样的类型,如果多个则报错
//@Resource //先按名字匹配没有,再按类型.而按类型的前提是只有一个此类型的bean
private UserService userService600;
public void sayOk() {
System.out.println("UserAction 的sayOk()");
//这里会输出userService的哈希值
System.out.println("userAction 装配的 userService600属性=" + userService600);
userService600.hi();
}
}
发现一个有趣的事情:
配置文件中只保留userService200,userAction文件中如下:
@Resource //先按名字匹配没有,再按类型.而按类型的前提是只有一个此类型的bean
private UserService userService600;
public void sayOk() {
System.out.println("UserAction 的sayOk()");
//这里会输出userService的哈希值
System.out.println("userAction 装配的 userService600属性=" + userService600);
userService600.hi();
按名字匹配没有,按类型原来不像第一种写不行哦~~~
后面写法直接写bean的全类名和id的,只能按名字查找.
会报错:
反思:
- 其实在Test文件中逐个ioc.getBean()是可以获取到每一个bean的哈希值的,值不同,各是各的.
- 而Action文件中看注入的是哪个,主要看@Resource 有没带type和name,有则按Resource配置的找,没有就先按名字后按类型.
- @Autowired 要看bean唯一与否,唯一就装配完事(按类型),不唯一就按名字装配,名字找不到就报错.
- 还要注意一点,注入的Resource的name肯定是容器中有的,写一个不存在的编译的时候直接就报错了,如图:
而写了容器中有的bean的名称,不管下边属性名怎么样,有没有/是什么都无所谓,通通按照指定的容器名称的bean对象进行注入.例如:
补充用法:
使用@Autowired也可以指定id进行组装,需要和@Qualifier两个注解都一起写上
@Autowired 单独用是先按类型,单个直接注入. 多例就按名字,多例的话名字就一定要有.
@Qualifier(value = “userService300”)//这时装配的是id= userService300,指定id=userService300的userService对象进行装配
//如果不写 @Qualifier(value = “userService300”),默认是按照下面的id,即userService600来进行组装的
package com.elf.spring.component;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
/**
* @author 45
* @version 1.0
* @Controller 标识该类是一个控制器Controller, 通常这个类是一个Servlet
*/
@Controller
public class UserAction {
//xml配置 ref
//@Autowired
//说明: @Autowired + @Qualifier(value = "userService02") 组合也可以完成指定 name/id 来进行自动装配
//指定id进行组装, 也可以使用@Autowired 和 @Qualifier(value = "userService02")
// 这时,是装配的 id=userService02 , 需要两个注解都需要写上
/** @Autowired 若这里注解为 @Autowired,属性名写userService400:
需要注销配置文件里200和300,只留注解扫描包那个就会成功
此时是按唯一bean,类型来做的,至于名字叫什么无所谓!!!
此时唯一能注入的就是通过注解默认到类名首字母小写的bean
**/
/**
* @Resource(name = "userService200")
* /**这里由于@Resource已经指定了id,把名字为userService的对象注入/装配到属性上
* 至于下面的属性名称为userService600或者别的什么已经没有意义了不考虑
*/
//@Resource(name = "userService200")
//@Resource(type = UserService.class)//这是要求容器中只能由一个这样的类型,如果多个则报错
//@Resource //先按名字匹配没有,再按类型.而按类型的前提是只有一个此类型的bean
//补充:使用@Autowired也可以指定id进行组装,需要和@Qualifier两个注解都一起写上
@Autowired //单独用是先按类型,单个直接注入. 多例就按名字,多例的话名字就一定要有
@Qualifier(value = "userService300")//这时装配的是id= userService300,指定id=userService300的userService对象进行装配
//如果不写 @Qualifier(value = "userService300"),默认是按照下面的id,即userService600来进行组装的
private UserService userService600;
public void sayOk() {
System.out.println("UserAction 的sayOk()");
//这里会输出userService的哈希值
System.out.println("userAction 装配的 userService600属性=" + userService600);
userService600.hi();
}
}
测试类
package com.elf.spring.test;
import com.elf.spring.component.UserAction;
import com.elf.spring.component.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author 45~
* @version 1.0
*/
public class AutoTest {
//通过注解来配置Bean
@Test
public void setProByAutowired() {
ApplicationContext ioc =
new ClassPathXmlApplicationContext("beans06.xml");
UserService userService = ioc.getBean("userService", UserService.class);
System.out.println("ioc容器中的userService=" + userService);
userService.hi();
UserService userService200 = ioc.getBean("userService200", UserService.class);
System.out.println("ioc容器中的userService200=" + userService200);
UserAction userAction = ioc.getBean("userAction", UserAction.class);
// //System.out.println("userAction=" + userAction);
userAction.sayOk();
//
UserService userService300 = ioc.getBean("userService300", UserService.class);
System.out.println("ioc容器中的userService300=" + userService300);
//
// System.out.println("userService=" + userService);
// System.out.println("userService200=" + userService200);
// System.out.println("userService300=" + userService300);
}
}
虽然写的属性id是userService600,但实际上装配的是userService300.
@Autowired + @Qualifier(value = “userService300”) 组合也可以完成指定 name/id 来进行自动装配.
可以直接由@Resource(name=“userService300”)一条指令代劳.
总结: 就是反着来,先按名字后按类型是@Resource. 但是其实也没那么多要求,@Autowired可以理解为按名字的,因为要先看是不是一个bean,类型不行还是走名字,只有一个bean我管你走什么?
不管哪种注解, 规范地按照类名首字母小写写id(属性名),就可以注入!!!
一般情况下用@Resource,不过泛型依赖注入还得用@Autowired.
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!