基于注解配置bean,也可以实现自动装配,使用的注解是@Autowired @Resource
@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);
}
}
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的,只能按名字查找.
会报错:
反思:
补充用法:
使用@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”)一条指令代劳.