通过之前的Spring初识这一节,从初始者的角度实现Spring的存与取,但是所需要的步骤是比较多的,比较臃肿,冗余
指路——>初识 Spring 容器
因此需要学习更加简单的Bean对象的存与取。在Spring中想要更加简单的存储和读取对象的核心就是 使用注解 。在之后的学习中,注解将会给写代码带来极大的便利。
想要将 Bean对象更加简单的存储到 Spring 中, 前置工作 就是在 Spring 的配置文件(就是名字是自己起的 xml 配置文件)中设置组件 Component 的 根路径
<?xml version="1.0" encoding="UTF-8"?>
代码如上(建议使用时 直接复制粘贴 )
在之前的较为复杂的存储 Bean 对象时,就是在该配置文件中进行 Bean 对象的声明,现在不需要写得那么复杂,只需要配置上需要进行扫描的路径即可, base-package 我们的内容就是回头我们 需要扫描的路径 (每个人写的都可以不一样)。
如果想要将某类对象,或者方法的返回值存储到 Spring容器中,只需要添加上相应的注解,并且将其放在扫描路径下,Spring就可以自动的将对象进行存储。
至于为什么需要指定扫描路径,那是因为一个规模较大的项目中将会有太多太多的包、类型、方法,如果统统进行扫描,效率将会非常的低下
想要将对象存储到 Spring 中,有两种注解类型可以进行实现
类注解
方法注解
@Controller ,发音 [kənˈtrəʊlə®], 控制器存储
使用方法:
步骤一:需要被存储的对象
@Controller
public class ArtController {
public void func() {
System.out.println("Hello Controller~");
}
}需要注意的事:该类 必须要放在扫描路径底下 ;必须要 加上注解 @Controller
步骤二:用之前的方式读取到上面的信息 ArtController 对象验证出存储的成功
public class Start {
public static void main(String[] args) {
//1.获取 Spring 上下文
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
//2.获取 Bean 对象
ArtController artController = context.getBean("artController", ArtController.class);
//3.使用 Bean 对象
artController.func();;
}
}需要注意的是:在这里的 beanName 是类名 ArtController 的 第一个字母小写 得来的(一般情况下)
结果:
@Service ,发音 [ˈsɜːvɪs], 服务存储
使用方法:
步骤一:需要被存储的对象
@Service
public class ArtService {
public void func2() {
System.out.println("Hello Service~~");
}
}需要注意的事:该类必须要 放在扫描路径底下 ;必须要 加上注解 @Service
步骤二:用之前的方式读取到上面的信息 ArtService 对象验证出存储的成功
ArtService artService = context.getBean("artService", ArtService.class);
artService.func2();需要注意的是:在这里的 beanName 是类名 ArtService 的 第一个字母小写 得来的(一般情况下)
结果:
@Repository ,发音 [rɪˈpɒzətri], 仓库存储
使用方法:
步骤一:需要被存储的对象
@Repository
public class ArtRepository {
public void func3() {
System.out.println("hello Repository!");
}
}需要注意的事:该类必须要 放在扫描路径底下 ;必须要 加上注解 @Repository
步骤二:用之前的方式读取到上面的信息 ArtRepository 对象验证出存储的成功
ArtRepository artRepository = context.getBean("artRepository", ArtRepository.class);
artRepository.func3();需要注意的是:在这里的 beanName 是类名 ArtRepository的 第一个字母小写 得来的(一般情况下)
结果:
@Component ,发音 [kəmˈpəʊnənt], 组件存储
使用方法:
步骤一:需要被存储的对象
@Component
public class ArtComponent {
public void func4() {
System.out.println("hello Component!!");
}
}需要注意的事:该类必须要 放在扫描路径底下 ;必须要 加上注解 @Component
步骤二:用之前的方式读取到上面的信息 ArtComponent 对象验证出存储的成功
ArtComponent artComponent = context.getBean("artComponent", ArtComponent.class);
artComponent.func4();需要注意的事:在这里的 beanName 是类名 ArtComponent 的 第一个字母小写 得来的(一般情况下)
结果:
@Configuration ,发音 [kənˌfɪɡəˈreɪʃn], 配置存储
使用方法:
步骤一:需要被存储的对象
@Configuration
public class ArtConfiguration {
public void func5() {
System.out.println("Hello Configuration!~");
}
}需要注意的事:该类必须要 放在扫描路径底下 ;必须要 加上注解 @Configuration
步骤二:用之前的方式读取到上面的 ArtConfiguration 对象验证出存储的成功
ArtConfiguration artConfiguration = context.getBean("artConfiguration", ArtConfiguration.class);
artConfiguration.func5();需要注意的事:在这里的 beanName 是类名 ArtConfiguration 的 第一个字母小写 得来的(一般情况下)
结果:
写到这,可能就会有疑问了,上面五种注解有什么区别,用法、作用不是一模一样嘛,直接都使用其中的一个不就行了,为啥要五种
事实上,虽然用法一样,但是上面的 五种类注解指向了五种不同的类的用途 ,让别人一看见这个注解就知道这个类实现的都是些什么功能,就相当于车牌号,我们可以通过看车牌就可以知道车辆的归属地(京XXX——北京来的,浙XXX——浙江来的)
通过 Ctrl + 左键 点击对应的注释,发现 Controller、Repository、Service和 Configuration注解 ,都实现了 Component 注解的功能,它们 都算是 Component 的 “子类”
通过上面的例子,我们发现 beanName 是类的第一个字母小写,但如果类的名字第一个和第二个字母都是大写,再用相同的方法,就会报错,说没有这样的 beanName
查看原码:
public static String decapitalize(String name) {
if (name == null || name.length() == 0) {
return name;
}
//长度大于1 且 第一个字母和第二个字母是大写
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);
}通过查看原码,发现如果 第一个字母和第二个字母都为大写 ,beanName 就是 原来的类名 , 否则 就将 beanName 就将 首字母小写
方法注解是放在某个方法上,将 方法返回的值 存储到 Spring 容器中。
并且需要配合类注解进行使用,因为扫描路径下的类中也许会有很多很多的方法,如果只扫描有类注解的类中的方法,会提高效率
使用方法:
步骤一:需要被存储的方法返回值对象
@Component
public class ArtComponent {
@Bean
public Article func() {
Article article = new Article();
article.setId(1);
article.setName("人与自然");
article.setContent("内容介绍");
return article;
}
}步骤二:获取到存储的Bean对象
public class Start {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
Article article = context.getBean("addArticle",Article.class);
System.out.println(article);
}
}结果:
在此之前使用方法注解的 beanName 是方法名,但是有些方法名带有一定的功能属性,比如上面的 addArticle ,这样的名字显得有点不合适,因此可以给 Bean 对象进行 重命名操作
@Bean(name = "article") //重命名了一个名字,name = 可以省略
@Bean(name = {
"article","article2"}) //重命名多个名字,name = 可以省略花括号
同一个
获取对象,就是将对象取出来放到某个类中,也叫 对象注入 ,就是在前一节讲到的 DI
在此之前,获取对象的方式是先获取 Spring 上下文,再获取 Bean 对象,最后再使用 Bean 对象。
如果依赖关系非常多的时候,A依赖于B,B依赖于C,C依赖于D,用上面的方法进行获取对象将会变得非常的麻烦,需要用更加简洁的方式进行对象的注入
属性注入
构造方法注入
Setter 注入
下面将模拟将 Service 类注入到 Controller 类中,三种方式的使用方法
属性注入是三种注入方式中最简单的注入方式,使用注解 @Autowired 实现
步骤一:创建 Service 类
@Service
public class ArtService {
public Article func(int id) {
//伪代码 通过数据库查询用户信息
//。。。
Article article = new Article();
article.setId(id);
article.setName("三国演义");
article.setContent("三国内容简介");
return article;
}
}步骤二:创建 Controller 类,依赖于 Service 类
@Controller
public class ArtController {
//属性注入
@Autowired
private ArtService artService;
public Article findArticle(int id) {
return artService.func(id);
}
}步骤三:获取 Controller 类
public class Start {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
ArtController artController = context.getBean("artController",ArtController.class);
System.out.println(artController.findArticle(1));
}
}结果:
在注入 Service 类时,会先进行类型的查询,如果在 Spring 中查询到同类型的对象就直接返回,否则使用类名称进行查询,都没有结果,说明注入失败
需要在 构造方法上加 @Autowired
@Controller
public class ArtController {
//构造方法注入
private ArtService artService;
@Autowired
public ArtController(ArtService artService) {
this.artService = artService;
}
public Article findArticle(int id) {
return artService.func(id);
}
}当类中只有一个构造方法时,@Autowired 可以省略,在有多个构造函数的时候,不可以省略
设置 set 方法的时候需要加上 @Autowired 注解
@Controller
public class ArtController {
//Setter 注入
private ArtService artService;
@Autowired
public void setArtService(ArtService artService) {
this.artService = artService;
}
public Article findArticle(int id) {
return artService.func(id);
}
}@Autowired 注释不可以被省略
在注入时,除了 @Autowired 关键字外,还可以使用 @Resource 注解进行注入,拿属性注入举例
@Resource
private ArtService artService;@Component
public class ArtComponent {
@Bean(name = "article1")
public Article func1() {
Article article = new Article();
article.setId(1);
article.setName("水浒传");
article.setContent("水浒传内容");
return article;
}
@Bean(name = "article2")
public Article func2() {
Article article = new Article();
article.setId(1);
article.setName("红楼梦");
article.setContent("红楼梦内容");
return article;
}
}可以看见有两个 Article 类被存储在了 Spring 中,如果直接使用 @Autowired 或者 @Resource 就会报错,不晓得究竟想要注入哪个对象
public class Start {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
ArtController artController = context.getBean("artController",ArtController.class);
artController.findArticle();
}
}获取到 ArtController 类,对其进行使用
@Resource 注解是可以设置很多参数,可以进行 beanName 的设置,name = 不可以省略
public class ArtController {
@Resource(name = "article1")
private Article article;
public void findArticle() {
System.out.println(article);
}
}方法二:@Autowired + @Qualifier
如果一定要使用 @Autowired 注解,就需要配合 @Qualifier 一起使用,value = 可以省略
@Controller
public class ArtController {
@Autowired
@Qualifier(value = "article2")
private Article article;
public void findArticle() {
System.out.println(article);
}
} | 留言与评论(共有 0 条评论) “” |