Spring-(三)基于注解的DI

本文最后更新于:December 3, 2021 pm

Spring 是目前主流的 Java Web 开发框架,是 Java 世界最为成功的框架。Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。该框架是一个轻量级的开源框架,具有很高的凝聚力和吸引力。Spring 框架不局限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何 Java 应用都可以从 Spring 中受益。Spring 框架还是一个超级粘合平台,除了自己提供功能外,还提供粘合其他技术和框架的能力。

目录

1.实现步骤

  1. 加入依赖
  1. 创建类,并加入注解
  1. 创建spring配置文件。在配置文件中声明组件扫描器标签,用来指明注解在项目中的位置。而组件扫描器是扫描当前包及其子包。
  1. 使用注解创建对象,创建容器ApplicationContext。

2.注解-@Component

用法:@Component(value = “”)

用来创建对象,等同于<bean>的功能。value的值就是对象的名称,即bean中的id值,具有唯一性。

示例:

Student.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.tothefor.bao1;

import org.springframework.stereotype.Component;

/**
* @Author DragonOne
* @Date 2021/9/18 14:50
*/

@Component(value = "mystudent")
public class Student {
private String name;
private int age;

@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}

public void setName(String name) {
this.name = name;
}

public void setAge(int age) {
this.age = age;
}
}

在配置文件中声明组件扫描器:

1
2
3
4
5
6
7
8
9
10
<?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.tothefor.bao1" />

</beans>

其中,base-package 用来指定注解在你的项目中的包名,或者最顶级的父包,如:

1
<context:component-scan base-package="com" />

但一般不建议这样使用,因为扫描的路径比较多,会导致容器启动时间变慢。

测试类:

1
2
3
4
5
6
7
8
9
10
public class zhujieTest {
@Test
public void test01(){
String config = "bao1/applicationContext.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(config);
Student student = (Student) applicationContext.getBean("mystudent");
System.out.println(student);

}
}

这种是调用的类的无参构造方法。

也可以省略value,直接写对象名称,如:

1
@Component("mystudent")

如果在注解中省略value属性,即不指定对象名称。那么将由spring提供默认的名称,而这个默认的名称是:类名,但类名的首字母是小写。(如果类名是Student,那么默认名称为student。)如:

1
@Component

3.同Component用法的其他注解

以下三个和@Component功能一致,用法相同,但它们有更多的功能。而@Component一般用于与下面三个无关的类中,或那些没有指定具体功能的类。

3.1 @Repository

用在持久层的类,放在dao的实现类中,表示创建dao对象,而dao对象是能访问数据库的。

3.2 @Service

用在业务层的类,放在service的实现类中,表示创建service对象,而service对象是做业务处理,可以有事务等功能的。

3.3 @Controller

用在控制器层的类,放在控制器(处理器)的类中,表示创建控制器对象,而控制器对象能够接收用户提交的参数,显示请求的处理结果。

所以,以上三个是给项目的对象分层的。

4.组件扫描器扫描多个包的方式

  1. 使用多次组件扫描器
1
2
<context:component-scan base-package="com.tothefor.bao1" />
<context:component-scan base-package="com.tothefor.bao2" />
  1. 使用分隔符分号(;)或逗号(,)分隔多个包名
1
<context:component-scan base-package="com.tothefor.bao1;com.tothefor.bao2" />
  1. 指定父包
1
<context:component-scan base-package="com.tothefor" />

5.简单类型属性注入(@Value)

在需要的属性上使用,该注解的value属性用于指定要注入的值。使用该注解完成属性注入时,类中无需set方法;若有,则也可将其加到set方法上。

示例:

Student.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package com.tothefor.bao02;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
* @Author DragonOne
* @Date 2021/9/19 06:50
*/

@Component(value = "mystudent")
public class Student {
@Value("loooooo") //也可以简写成 @Value("loooooo")
private String name;
@Value("23") //也可以简写成 @Value("23")
private int age;

public Student() {
System.out.println("==无参构造方法==");
}

@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}

}


//有set方法
@Component(value = "mystudent")
public class Student {
private String name;
private int age;

public Student() {
System.out.println("==无参构造方法==");
}

@Value("loooooong")
public void setName(String name) {
this.name = name;
}

@Value("23")
public void setAge(int age) {
this.age = age;
}

@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}

}

applicationContext.xml

1
2
3
4
5
6
7
8
9
<?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.tothefor.bao02" />

</beans>

测试类:

1
2
3
4
5
6
7
@Test
public void test02(){
String config = "bao02/applicationContext.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(config);
Student student = (Student) applicationContext.getBean("mystudent");
System.out.println(student);
}

6.引用类型注入(@Autowired)

spring框架提供的注解,实现引用类型的赋值。使用的是自动注入原理,@Autowired 默认使用的是 byType 自动注入。

@Autowired 的使用也有两种,一种是在属性定义的上面,无需set方法;另一种是在set方法的上面。用法可参考 @Value 。

示例:

school.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package com.tothefor.bao03;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
* @Author DragonOne
* @Date 2021/9/19 07:27
*/

@Component(value = "myschool")
public class school {
@Value("aolg")
private String name;
@Value("23432412312")
private String tele;

@Override
public String toString() {
return "school{" +
"name='" + name + '\'' +
", tele='" + tele + '\'' +
'}';
}

public void setName(String name) {
this.name = name;
}

public void setTele(String tele) {
this.tele = tele;
}

public school() {
}
}

student.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.tothefor.bao03;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
* @Author DragonOne
* @Date 2021/9/19 07:28
*/

@Component(value = "mystudent")
public class Student {
@Value("looonngggg")
private String name;
@Value("23")
private int age;
@Autowired
private school sc;

public Student() {
System.out.println("==无参构造方法==");
}

@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", sc=" + sc +
'}';
}
}

applicationContext.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?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.tothefor.bao03" />
<!--不用注解时创建school对象-->
<bean id="myschool" class="com.tothefor.bao03.school">
<property name="name" value="qwertyuio" />
<property name="tele" value="1234578" />
</bean>

</beans>

测试类:

1
2
3
4
5
6
7
8
@Test
public void test03(){
String config = "bao03/applicationContext.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(config);
Student student = (Student) applicationContext.getBean("mystudent");
System.out.println(student);

}

6.1 @Autowired的byName自动注入

默认情况下,@Autowired 使用的是byType的自动注入,如果需要使用byName的自动注入,则需要添加一个注解,即:

  1. 在属性的上方加入@Autowired
  2. 再在属性的上方加入@Qualifier(value = “创建的对象的id”),value值是bean的id。表示使用指定名称的bean完成赋值。

两个注解没有先后顺序。

其他代码同上,唯一的区别是,在原有的基础上多加了一个@Qualifier注解:

1
2
3
@Autowired
@Qualifier(value = "myschool")
private school sc;

注意:在配置创建对象时,如果同时使用注解和配置文件,则配置文件中的会生效

6.2 @Autowired的required属性

是一个boolean类型的,默认为true,表示引用类型赋值失败,则程序报错并终止执行;为false,表示引用类型如果赋值失败,则程序正常执行,引用类型为null。

7.引用类型注入(@Resource)

使用该注解,要求JDK必须是6及其以上的版本,因为此注解是来自JDK的,而spring框架提供了对这个注解的功能支持。默认情况下是按名称(byName)注入。

同样,有两种用法,一种是无set方法时,在属性上面使用;另一种是在set方法上面使用。

注意:默认是byName,但如果使用byName自动注入赋值失败了,则会再次使用byType。

如:

1
2
@Resource
private school sc;

如果只想使用byName方式,则需要添加一个 name 属性,其name的值是bean的id。如:

1
2
@Resource(name="myschool")
private school sc;

经常改的用配置文件,不经常改的用注解。


本文作者: 墨水记忆
本文链接: https://tothefor.com/DragonOne/1142082378.html
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!