使用注解来存取对象

  • 一、配置扫描路径
  • 二、添加注解存储Bean对象
    • 2.1类注解
      • 2.1.1 @Controller存储
      • 2.1.2 @Service存储
      • 2.1.3 @Repository存储
      • 2.1.4 @Component存储
      • 2.1.5 @Configuration存储
      • 2.1.6 为什么有这么多类注解?
    • 2.2 Bean的命名规则
    • 2.3 方法注解@Bean
      • 2.3.1 重命名Bean
  • 三、获取Bean对象
    • 3.1 属性注入
    • 3.2 构造方法注入
    • 3.3 Setter注入
    • 3.4 三种注入方式的优缺点
    • 3.5 @Resource:另一种注入关键字
      • 3.5.1 经典面试题: @Resource和@Autowired的区别
    • 3.6 同一个类型下多个Bean报错

上篇文章中我们详细的讲解了Spring对象的存取和使用,感兴趣的朋友可以去看上篇文章Spring的创建和使用,但是上篇文章中讲的存取对象的方法相对来说有些繁琐,这篇文章我们就介绍使用注解的方式来进行存储对象吧~~

一、配置扫描路径

这里说的配置扫描路径的方式就是在spring的配置文件中配置一下存储对象的包的路径,只有被配置的包下的所有类,添加了注解才能被识别并注册到Spring中。
试想一下,如果不配置路径,那么较大的项目中有成百上千个类,那么就要一个一个类挨着扫描,性能很低。

在配置文件中添加:

<?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"><!-- 设置需要存储到 spring 中的 bean 根目录 --><content:component-scan base-package="com.beans"></content:component-scan>
</beans>

二、添加注解存储Bean对象

配置好扫描路径后,就可以通过添加注解将对象存储在Spring中,有以下两种注解类型:

  • 类注解:@Controller、@Service、@Repository、@Component、@Configuration
  • 方法注解:@Bean

注意事项:

  • 即使在配置文件中配置了bean扫描路径,但是五大类注解是不能省略的。
  • 即使添加了五大类注解,但是类没有放在spring配置的根路径下,那么类也不能注入到spring中。

2.1类注解

2.1.1 @Controller存储

使用@Controller存储bean:

@Controller
public class UserController {public void sayHi(String name){System.out.println("Hi "+name);}
}

使用之前的方式获取UserController对象:

/*** 启动类*/
public class App {public static void main(String[] args) {//1.获取Spring上下文ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");//2.得到beanUserController userController=context.getBean(UserController.class);//3.使用beanuserController.sayHi("java");}}

2.1.2 @Service存储

使用@Service存储bean:

@Service //将当前bean对象存储到spring中
public class UserService {public void sayHi(String name){System.out.println("Hi "+name);}
}

使用之前的方式获取UserService 对象:

/*** 启动类*/
public class App {public static void main(String[] args) {//1.获取Spring上下文ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");UserService userService = context.getBean("userService", UserService.class);userService.sayHi("javaee");}}

2.1.3 @Repository存储

使用@Repository存储bean:

@Repository //将对象注入到spring中
public class UserRepository {public void sayHello(String name){System.out.println("Hello "+name);}
}

使用之前的方式获取UserRepository 对象:

/*** 启动类*/
public class App {public static void main(String[] args) {//1.获取Spring上下文ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");UserRepository userRepository = context.getBean("userRepository", UserRepository.class);userRepository.sayHello("世界");}}

2.1.4 @Component存储

使用@Component存储bean:

@Component //将对象注入到spring中
public class UserComponent {public void sayHello(String name){System.out.println("Hello "+name);}
}

使用之前的方式获取UserComponent 对象:

/*** 启动类*/
public class App {public static void main(String[] args) {//1.获取Spring上下文ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");UserComponent userComponent = context.getBean("userComponent", UserComponent.class);userComponent.sayHello("world");}}

2.1.5 @Configuration存储

使用@Configuration存储bean:

@Configuration //将对象注入到spring中
public class UserConfiguration {public void sayHello(String name){System.out.println("Hello "+name);}
}

使用之前的方式获取UserConfiguration 对象:

/*** 启动类*/
public class App {public static void main(String[] args) {//1.获取Spring上下文ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");UserConfiguration userConfiguration = context.getBean("userConfiguration", UserConfiguration.class);userConfiguration.sayHello("world");}}

2.1.6 为什么有这么多类注解?

我们来看一下除了Component之外其他四个类注解的源码,不难发现,他们都是依靠@Component实现的,因此可以说@Component式其他四个类注解的父类。



那么这些类的功能都相同,为什么还要有这么多类注解呢?
其实就像我们国家的车牌一样,会根据省份进行划分,省份会进一步根据省内的城市进行划分,这样交警叔叔在看到车牌号后,一下就可以辨别这个车是哪个省哪个城市的车。
那么spring中的类注解也是同样的道理,就是通过这些注解来对我们的工程进行分层,每个注解代表不同的用途,那么这样当程序员一看到这个注解就知道这个类是用来做什么的。

2.2 Bean的命名规则

1.类名使用大驼峰命名,读取的时候将首字母小写即可。

2.类名的首字母和第二个字母都是大写,则在读取的时候使用原类名。

这是为什么呢?
我们就要来看看bean命名规则的源码:

它使用了JDK中的decapitalize方法:

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.3 方法注解@Bean

注意~~
方法注解必须配合五大类注解其中之一进行使用才有效,否则无效。

@Component
public class UserBeans {@Bean  //将当前方法返回的对象存储到spring中,默认bean是方法名public User getUser(){User user=new User();user.setId(1);user.setName("张三");user.setPassword("123456");return user;}
}
/*** 启动类*/
public class App {public static void main(String[] args) {//1.获取Spring上下文ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");User user1=context.getBean("getUser",User.class);System.out.println(user1);}}

2.3.1 重命名Bean

@Component
public class UserBeans {@Bean(name="user1")  //将当前方法返回的对象存储到spring中,默认bean是方法名public User getUser(){User user=new User();user.setId(1);user.setName("张三");user.setPassword("123456");return user;}
}
/*** 启动类*/
public class App {public static void main(String[] args) {//1.获取Spring上下文ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");User user1=context.getBean("user1",User.class);System.out.println(user1);}}


在对Bean进行重命名之后,就不可以使用原来的类名首字母小写和方法名进行获取对象。

三、获取Bean对象

存储完对象,就可以来取对象了。
获取对象又叫也叫做对象装配,是把对象取出来放到某个类中,也叫对象注入

分为以下三种注入方式:

  1. 属性注入
  2. 构造方法注入
  3. Setter注入

以下注入方式的演示,都是将Service注入到Controller类中。

3.1 属性注入

属性注入就是在属性上加上@Autowired,将Service注入到Controller类中。

Service类实现:

@Service //将当前bean对象存储到spring中
public class UserService {public void sayHi(String name){System.out.println("Hi "+name);}/*** 根据id获取用户* @param id* @return*/public User getUserById(int id){//伪代码User user=new User();user.setId(id);user.setName("雪雪");user.setPassword("1234");return user;}
}

Controller类:


@Controller
public class UserController {//1.属性注入@Autowiredprivate UserService userService;public void sayHi(String name){System.out.println("Hi "+name);}public User getUserId(Integer id){//伪代码return userService.getUserById(id);}
}

获取Controller中的getUserId的方法:

/*** 启动类*/
public class App {public static void main(String[] args) {//1.获取Spring上下文ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml")UserController userController = context.getBean("userController",UserController.class);System.out.println(userController.getUserId(10));}
}

3.2 构造方法注入

@Controller
public class UserController2 {private UserService userService;//2.构造方法注入@Autowiredpublic UserController2(UserService userService){this.userService=userService;}public void sayHi(String name){System.out.println("Hi "+name);}public User getUserId(Integer id){//伪代码return userService.getUserById(id);}
}

注意:如果当前类中只有一个构造方法,那么不加@Autowied注解也是可以获取到User对象,但是如果有多个构造方法,那就必须加@Autowied注解。

3.3 Setter注入

@Controller
public class UserController3 {private UserService userService;//3.setter注入@Autowiredpublic void setUserService(UserService userService) {this.userService = userService;}public void sayHi(String name){System.out.println("Hi "+name);}public User getUserId(Integer id){//伪代码return userService.getUserById(id);}
}

Setter注入必须加 @Autowired注解,如果不加,就会报NullPointerException。

3.4 三种注入方式的优缺点

  • 属性注入:写法最简单,也最简洁。缺点是不通用,它只适用于loC框架,非loC框架不可用,只有在使用时会出现空指针异常。
  • Setter注入:Spring 早期版本推荐的注入方式,它的通用性不如构造方法注入。
  • 构造方法注入:缺点是可能存在传递多个参数来实现构造方法的初始化,会导致代码很臃肿,那么如果出现了这种情况那么开发者应该反思自己写的代码是否符合单一职责的设计模式了;优点是通用性更好,并且他能保证在调用对象之前,此对象一定是存在的。Spring后期版本官方推荐的注入方式。

3.5 @Resource:另一种注入关键字

在进行获取对象时,除了可以使用@Autowired注解外,还可以使用@Resource注解。

@Controller
public class UserController5 {private UserService userService;@Resourcepublic void setUserService(UserService userService) {this.userService = userService;}public void sayHi(String name){System.out.println("Hi "+name);}public User getUserId(Integer id){//伪代码return userService.getUserById(id);}
}

3.5.1 经典面试题: @Resource和@Autowired的区别

  1. 出身不同:@Autowired来自Spring,而 @Resource来自于JDK。
  2. 使用时设置的参数不同:@Autowired只支持required参数设置,@Resource支持更多的参数设置。如name等。
  3. 支持不同:@Autowired支持属性注入、构造方法注入、Setter注入,而@Resourc只支持属性注入和Setter注入,不支持构造方法注入。

3.6 同一个类型下多个Bean报错

@Component
public class UserBeans {@Bean(name="user1")  //将当前方法返回的对象存储到spring中,默认bean是方法名public User getUser(){User user=new User();user.setId(1);user.setName("张三");user.setPassword("123456");return user;}@Bean(name="user2")public User getUser2(){User user=new User();user.setId(2);user.setName("李四");user.setPassword("456");return user;}
}
@Controller
public class UserController6 {@Resourceprivate User user;public void sayHi(){System.out.println(user);}
}

怎么解决呢?

  1. 使用@Resource(name = “user1”)定义
@Controller
public class UserController6 {@Resource(name="user2")private User user;public void sayHi(){System.out.println(user);}
}

  1. 使用@Autowired+@Qualifier注解定义
@Controller
public class UserController6 {@Autowired@Qualifier(value="user1")private User user;public void sayHi(){System.out.println(user);}
}

【Spring】万字详解使用注解来存取对象相关推荐

  1. 微服务开发的入门级框架Spring Boot详解:注解

    2019独角兽企业重金招聘Python工程师标准>>> 通过前两章节的介绍,大家应该对Spring Boot有了些许的认识,也感觉到了这个框架带来的便利,下面我将讲解SpringBo ...

  2. Spring 体系结构详解

    Spring 体系结构详解 核心容器(Core Container) Core和Beans模块提供了Spring最基础的功能,提供IOC和依赖注入特性.这里的基础概念是BeanFactory,它提供对 ...

  3. springMVC详解以及注解说明

    springMVC详解以及注解说明 基于注释(Annotation)的配置有越来越流行的趋势,Spring 2.5 顺应这种趋势,提供了完全基于注释配置 Bean.装配 Bean 的功能,您可以使用基 ...

  4. [转载]Spring配置文件详解一:

    2019独角兽企业重金招聘Python工程师标准>>> 原文地址:Spring配置文件详解一:<context:annotation-config/>与<conte ...

  5. java注解 源码_详解Java注解教程及自定义注解

    详解Java注解教程及自定义注解 更新时间:2016-02-26 11:47:06   作者:佚名   我要评论(0) Java注解提供了关于代码的一些信息,但并不直接作用于它所注解的代码内容.在这个 ...

  6. Spring入门详解

    typora-copy-images-to: upload Spring入门详解 Spring框架是Java开发中最常用的框架,功能非常强大 源码下载:Spring Framework jar包.文档 ...

  7. Spring IoC详解

    Spring IoC详解 原文地址:Spring IoC详解 写在最前 本文将主要写Spring最核心的部分,为什么写这篇的原因也是因为在刚开始学习Spring的时候,学得太粗糙了.感觉学了个皮毛,从 ...

  8. SpringBoot教程(13) JUnit5详解 常用注解 BeforeEach BeforeAll ParameterizedTest RepeatedTest

    JUnit5详解 常用注解 BeforeEach BeforeAll ParameterizedTest RepeatedTest 一.前言 1. 引入test包 二.注解 三.测试案例 1. @Be ...

  9. Spring源码(八):Spring事务详解

    Spring事务详解 一.事务执行流程 二.Spring事务切面 三.事务切面的Pointcut和Advice 四.注解事务的源码分析 五.Sping事务的传播属性 六.Sping事务的异常校验 七. ...

最新文章

  1. MSN Cartoon 试用
  2. 图解一次Linux挂载操作和mount命令基本用法
  3. 【slighttpd】基于lighttpd架构的Server项目实战(4)—简单的echo服务器
  4. 剖析java中的String之__拼接
  5. 首次落地中国大陆的OpenInfra:中国对于开源做出的贡献力量已不可忽视
  6. DataGridView多线程更新数据的问题的解决办法
  7. ubuntu MySQL-python 安装失败解决方法
  8. 面试中的排序算法总结
  9. Microsoft SQL Server Integration Service文章总结
  10. 数据结构 以数组的形式存储数据(c语言 干货满满)
  11. 新浪通行证在线申诉找回密码业务逻辑错误导致严重安全漏洞
  12. cs231n学习笔记 CNN 目标检测 定位 分割
  13. 关于word粘贴图片显示不全的解决办法
  14. UG编程加工之非切削移动
  15. 马虎词汇教程1-5(转载)
  16. 485通讯问题及解决调试方案提炼
  17. python实验过程中遇到的问题以及解决办法_20183413 2029-2020-2《Python程序设计》实验一报告...
  18. 如何挑选文档管理软件?
  19. linux atop日志查看,A - atop - 监控Linux系统资源与进程的工具 - 《Linux命令大全搜索工具(旧版)》 - 书栈网 · BookStack...
  20. Acwing1072 树的最长路径(树的直径)树形Dp 记忆化搜索

热门文章

  1. 浙里办单点登录-PHP-TP5-轻松上手
  2. 课程目标以及课堂作业
  3. 数字化转型:AI中台如何在企业中落地
  4. python:Redis面试题合集1
  5. Android应用生死轮回的那些事儿(2) - PackageManager
  6. linux使用apache搭建http服务器(文件服务器)
  7. 爬虫高阶必备,JavaScript逆向,收藏在看
  8. HTML之样式定义、div布局、按钮布局
  9. Java入门_主函数+数据类型
  10. 基于 HTML5 + Canvas 实现楼宇自控系统