使用注解标识类存取对象
和我们上面使用Bean类注入spring-config.xml文件来说,这样还是比较麻烦的,因为需要我们手动的将对象引入. 所以我们又使用了一个更加简单的方式:使用注解来标识类 下面我们就来具体的看一下吧!
1.配置扫描路径
因为我们不是采用手动的注入的方式了,而是使用扫描的方式. 那么我们到底是扫描哪个文件里面的类呢? 我们就可以再Spring的配置文件中设置我们要扫描的路径 Spring-config.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:content="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">
<content:component-scan base-package=""></content:component-scan>
</beans>
我们扫描的时候只扫描base-package里面的类 ,不再里面的类即使加入了注解也不会被扫描. 这个base-package里面的内容需要我们自己添加.就是存放bean对象的根目录
为什么要指定只加载特定目录里面的类呢? 因为不是所有的类,我么都想要把他放到Spring容器里面的.有的就是普通的类对象 所以,我们就只加载特定的要放入的类
但是只是将类放到这个包里面就可以运行吗?答案是当然不对的,还需要在类的前面加上注解,这两个缺一不可,下面我们就来介绍一下这个注解
2.存入对象
1.五大类注解
为了描述每一个类所属的功能,让人一看就知道这个类是干什么用的,我们就引入这个五大类的注解来帮助我们区分 @Configuration 配置类 一些负责配置信息的类 @Controller 控制类 主要是验证前端发过来的参数 @Service 服务类 数据的处理和接口的调用(Dao层的接口) @Repository 仓库类 主要是对数据库的操作,也叫做Dao类 @Component 组件类 一些外部实现的工具类
要注意,每一个要加入Spring容器中的类的前面都要加上这个注解标识,这样的话才可以标识它已经加入到了容器中,要不然表示没有加入
五大类之间的关系
通过查看源码,我们发现,Component是其他四个类的父类
其他几个类也是这样的,都是Component的子类
beanName的问题
我们得到类的时候,需要得到类的名字,那个时候我们就是使用类的小驼峰的方式 比如说:UserController的BeanName就是userController 但是如果ClassName是APIController呢?难道要转为aPIController? 其实不是的,而是和他的ClassName一样还是APIController
我们到AnnotationBeanNameGenerator类里面看一下源码是怎么实现的
public static String decapitalize(String name) {
if (name == null || name.length() == 0) {
return name;
}
if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) &&
Character.isUpperCase(name.charAt(0))){
return name;
}
char chars[] = name.toCharArray();
chars[0] = Character.toLowerCase(chars[0]);
return new String(chars);
}
也就是说当开头只有一个大写字母的话,那么就将第一个大写字母变为小写的 如果开头有两个以上的大写字母 ,那么就还是原来的大写字母不变
2.方法注解@Bean
和前面直接得到一个完整的类来说,还有一种获取到类的方式是通过方法来获取到类,也就是说这个方法的返回值直接就是一个类
要想要将这个返回的类放入Spring中要怎么做呢?(注意是方法返回的类) 采取的做法就是使用方法注解
我们又新创建出一个类GetUser,在这个方法中有一个Get方法,它的返回值就是User对象.
@Controller
public class GetUser {
@Bean
public User get(){
User user=new User();
return user;
}
}
注意事项:
- @Bean注解要放到方法的前面
- GetUser类也要加上五大注解中的一个,为了减少Spring的扫描范围,加上五大类注解的表示它里面含有Bean方法,这样Spring就会将被Bean修饰的类加入到Spring中
另外,我们获取到类的时候,使用的是方法名,而不是大驼峰或小驼峰了
User user=context.getBean("get",User.class);
Bean对象改名
我们上面获取到Bean修饰的方法的类使用的是方法的名字,但是这样是不太合理的,因为我们想要得到的是类,但是我们却传入了方法的名字. 所以,我们最好给每一个传入的对象都起一个别的名字
- 在Bean后面写一个括号,加上name属性,名字使用字符串
- 还可以有多个名字,多个字符串使用大括号括起来,字符串之间使用逗号分隔
- name这个属性也可以省略,可以直接写大括号或字符串
@Controller
public class GetUser {
@Bean(name = "user1")
public User get1(){
User user=new User();
user.setId(1);
user.setName("lxy");
return user;
}
@Bean(name ={"user2","cx"} )
public User get2(){
User user=new User();
user.setId(2);
user.setName("cx");
return user;
}
@Bean({"user3","lx"} )
public User get3(){
User user=new User();
user.setId(2);
user.setName("cx");
return user;
}
}
使用了新的名字之后,我们就不可以再使用方法来获取类了 就只可以使用别名来获取类
3.得到Bean对象
现在我们来说三种得到Bean对象的三个简单方式:
1.属性注入
使用Autowired注入UserService属性
@Controller
public class UserController {
@Autowired
private UserService userService;
public void print(){
userService.print();
}
}
2.构造方法注入
将Autowired注入构造方法那里,当我们构造这个方法的时候,就会将UserService注入这个参数里面 这个和属性直接注入相比是懒加载了,当然这个也是官方推荐的一种方式
@Controller
public class UserController {
private UserService userService;
@Autowired
public UserController(UserService userService){
this.userService=userService;
}
public void print(){
userService.print();
}
}
另外,如果一个类里面只有一个构造方法,那么就i不用使用Autowired进行修饰了
3.setter方法注入
使用setter方法注入,还是需要有Autowired注释
@Controller
public class UserController {
private UserService userService;
@Autowired
public void setUserService(UserService userService) {
this.userService = userService;
}
public void print(){
userService.print();
}
}
4.三者的优缺点
属性注入: 优点:写法简单 缺点:只限于IOC容器下,通用性不好 构造方法注入: 优点:通用性高,在使用注入对象的时候,该注入对象早已经被构造过了,可以直接使用方法了 缺点:构造方法带有的参数可能会很多,影响使用 setter注入: 优点:早期Spring推荐的做法 缺点:和构造方法注入相比,setter注入的通用性低
5.@Resource
上面的Autowired是Spring框架提供的,但是Resource是Jdk提供的, Resource和Autowired都是提供对象注入的 但是,Resource支持属性注入和setter注入,但是它不支持构造方法注入
4.@Autowired和@Resource的区别
- 出身不同:
Autowired属于Spring框架 Resource属于Jdk - 使用范围不同:
Autowired可以作用于构造方法注入,属性注入,setter注入 Resource可以作用于属性注入,setter注入 - 参数个数不同
Autowired只有一个参数:required Resource有多个参数:name,lookup,type,…
5.一个Bean对象被注入多次
如果一个Bean对象被注入了多次,那么获取对象的时候,我们怎么来区分到底是哪一个对象呢?
@Controller
public class GetUser {
@Bean(name = "user1")
public User get1(){
User user=new User();
user.setId(1);
user.setName("lxy");
return user;
}
@Bean(name ={"user2","cx"} )
public User get2(){
User user=new User();
user.setId(2);
user.setName("cx");
return user;
}
@Bean({"user3","lx"} )
public User get3(){
User user=new User();
user.setId(2);
user.setName("lx");
return user;
}
}
上面一共有三个user对象,那么怎么确定要的是哪一个
1.直接写Bean的名字
第一个方法就是直接清楚的描述类的名字. 使用@Resource和@Autowired属性注入的方式,只不过在对象的名上面指定对象的名字
@Controller
public class UserController {
@Resource
private User user2;
public void print(){
System.out.println(user2);
}
}
2.使用@Resource的name属性
在@Resource的name属性中设置对象的名字,写什么名字就注入什么名字的对象
@Controller
public class UserController {
@Resource(name = "user1")
private User user;
public void print(){
System.out.println(user);
}
}
这样的好处是我们不必更改UserController中的 user的名字,只要指定这个user所匹配的对象的名字就可以,相当于重命名了
3.使用@Autowired+@Qualifier
这种方法和@Resource异曲同工,因为Autowired没有name属性,所以我们采用Qualifier来帮助我们
@Controller
public class UserController {
@Qualifier(value = "user2")
@Autowired
private User user;
public void print(){
System.out.println(user);
}
}
|