Spring框架(6) —— 基于注解的配置方式

简介

  • 之前我们学习了基于xml文件的配置方法,今天我们学习基于注解的配置方法

目录结构

  • src
    • main
      • java
        • cn.water
          • POJO.java
          • TextEditor.java
          • SpellCheck.java
      • resources
        • Beans.xml
    • test
      • java
        • cn.water.test
          • SpringTest.java

开启注解扫描

  • 在使用基于注解的注入依赖之前,我们需要在 Spring 配置文件中指定需要 Spring 去自动扫描出注解配置的文件的包。一旦 被配置后,你就可以开始注解你的代码,表明 Spring 会自动连接值到属性,方法和构造函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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
http://www.springframework.org/schema/context/spring-context.xsd">

<!-- 开启注解扫描 -->
<context:component-scan base-package="cn.water"></context:component-scan>

</beans>

定义容器

  • 让我们来看看几个重要的注解,并且了解它们是如何工作的。
  • @Component 注解:用于定义一个Bean对象。
    • Value属性:用于指定 Bean对象的唯一标识。
      • 默认为当前类名,首字母小写。
  • 另外,和 @Component 注解功能相同的注解还有另外三个,除了定义 Spring Bean 的功能之外,它们主要用于标识三层构架:
    • @Controller:表现层
    • @Service:业务层
    • @Repository:持久层

实体类

1
2
3
4
5
@Component("pojo")
public class POJO {


}

作用范围

  • @scope注解:用于指定Bean对象的作用范围。
    • Value属性:singleton单例(默认)、prototype多例

单例

实体类

1
2
3
4
5
6
@Component("pojo")
@Scope("singleton")
public class POJO {


}

多例

实体类

1
2
3
4
5
6
@Component("pojo")
@Scope("prototype")
public class POJO {


}

生命周期

实体类

  • @PreDestroy:用于指定Bean对象的销毁方法。
  • @PostConstruct:用于指定Bean对象的初始化方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Component("pojo")
public class POJO {

/* 初始化方法 */
@PostConstruct
public void init() {
System.out.println("POJO类:初始化成功!");
}

/* 销毁方法 */
@PreDestroy
public void destroy() {
System.out.println("POJO类:销毁成功!");
}

}

生命周期/作用范围

  • 立即加载 非常符合 单例模式 的特点,ApplicationContext 就属于立即加载

    • 所以一旦我们创建 ApplicationContext 容器,就会立即加载所有的POJO对象,即使我们还没有获取对象;而一旦我们注销 ApplicationContext 容器,POJO对象就被销毁了。
  • 多例模式 更符合 延迟加载,也就是 BeanFactory 容器。

    • 如果在多例模式在,使用 ApplicationContext 容器的话,那么 ApplicationContext 容器 的特点就会失效,并且改成 BeanFactory 容器的特点。就是说,只有我们从容器中获取POJO对象时,POJO对象才会被创建;而且只有POJO对象被销毁时,销毁方法才会执行。

实体类

POJO01.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Component("pojo01")
@Scope("singleton")
public class POJO01 {

/* 初始化方法 */
@PostConstruct
public void init() {
System.out.println("POJO类:初始化成功!");
}

/* 销毁方法 */
@PreDestroy
public void destroy() {
System.out.println("POJO类:销毁成功!");
}

}

POJO02.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Component("pojo02")
@Scope("prototype")
public class POJO02 {

/* 初始化方法 */
@PostConstruct
public void init() {
System.out.println("POJO类:初始化成功!");
}

/* 销毁方法 */
@PreDestroy
public void destroy() {
System.out.println("POJO类:销毁成功!");
}

}

测试类

单例

  • ApplicationContext容器创建时,Bean对象初始化。
  • ApplicationContext容器销毁时,Bean对象销毁。
1
2
3
4
5
6
7
8
@Test
public void test01() {
/* 1、加载配置文件,初始化Bean对象 */
ApplicationContext app = new ClassPathXmlApplicationContext("Scope_LifeCycle/Beans.xml");
/* 2、注销容器 */
((ClassPathXmlApplicationContext)app).close();

}

多例

  • 从容器中获取Bean对象时,Bean对象初始化。
  • Bean对象被Java回收器机制销毁时销毁。
1
2
3
4
5
6
7
8
9
@Test
public void test02() {
/* 1、加载配置文件,初始化Bean对象 */
ApplicationContext app = new ClassPathXmlApplicationContext("Scope_LifeCycle/Beans.xml");
/* 2、获取Bean对象 */
POJO02 pojo02 = app.getBean("pojo02", POJO02.class);
/* 3、注销容器 */
((ClassPathXmlApplicationContext)app).close();
}

运行结果

单例

  • POJO(单例)初始化
  • POJO(单例)销毁
1
2
POJO类:初始化成功!
POJO类:销毁成功!

多例

  • POJO(单例)初始化
  • POJO(多例)初始化
  • POJO(单例)销毁
1
2
3
POJO类:初始化成功!
POJO类:初始化成功!
POJO类:销毁成功!

依赖注入

@Resource 注解

  • 基于注解的依赖注入,不需要构造方法或者Setter方法。
  • 工作原理:
    • Bean对象
      • Key:@Component 注释 Value属性值
        • pojo
      • Value:被 @Component 注释的类
        • POJO
    • POJO对象
      • 对应Key:@Resource注释的 name属性值
        • pojo

SpellCheck

1
2
3
4
5
@Component("check")
public class SpellCheck {


}

TextEditor

  • @Resource注解 name属性:依赖注入
1
2
3
4
5
6
7
@Component("editor")
public class TextEditor {

@Resource(name = "check")
private SpellCheck spellCheck;

}

@Autowired 注解

  • 自动按照类型注入。当使用注解注入属性时,set方法可以省略。它只能注入其他bean类型。当有多个
    类型匹配时,使用要注入的对象变量名称作为bean的id。
  • 在 @Autowired 注解中,Spring 框架先对应Bean的Value而不是Key。
  • 工作原理:
    • Bean对象
      • Key:@Component 注释 Value属性值
        • pojo
      • Value:被 @Component 注释的类
        • POJO
    • POJO对象
      • 对应Value:被 @Autowired 注释的类成员的类型
        • POJO

SpellCheck

1
2
3
4
5
@Component("check")
public class SpellCheck {


}

TextEditor

  • @Autowired注解:自动注入依赖
1
2
3
4
5
6
7
@Component("editor")
public class TextEditor {

@Autowired
private SpellCheck spellCheck;

}

@Qualifier 注解

  • @Qualifier:和@Autowired一起使用,解决无法注入相同的数据类型不同变量的问题。
    • 在类成员上,和@Autowired一起使用。
    • 在方法上,可以单独使用。
  • 工作原理:
    • Bean对象
      • Key:@Component 注释 Value属性值
        • pojo
      • Value:被 @Component 注释的类
        • POJO
    • POJO对象
      • 对应Value:被 @Autowired 注释的类成员的类型
        • POJO
      • 对应Key:@Qualifier注释 value属性的值
        • pojo

SpellCheck

1
2
3
4
5
@Component("check")
public class SpellCheck {


}

TextEditor

  • @Autowired注解:自动注入依赖
  • @Qualifier注解:指定被注入的Bean对象的id
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Component("editor")
public class TextEditor {

/* 成员变量 */
@Autowired
@Qualifier("check")
private SpellCheck spellCheck01;

@Autowired
@Qualifier("check")
private SpellCheck spellCheck02;


/* Getter:测试是否注入成功 */
public SpellCheck getSpellCheck01() {
return spellCheck01;
}

public SpellCheck getSpellCheck02() {
return spellCheck02;
}
}

@Value 注解

  • 自动按照类型注入,它可以使用spring中SqEL表达式。

SpellCheck

1
2
3
4
5
6
7
8
9
10
@Component("check")
public class SpellCheck {

@Value("#{'Cat'}")
public String name;

@Value("#{1}")
public int id;

}

TextEditor

  • @Value注解:指定被注入的Bean对象的id
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Component("editor")
public class TextEditor {

/* 成员变量 */
@Value("#{'Cat'}")
private String s;

@Value("#{999}")
private int i;

@Value("#{12.13}")
private float f;

@Value("#{check}")
private SpellCheck spellCheck;

@Value("#{check.name}")
private String username;

@Value("#{check.id}")
private int userid;

}
-------------本文结束-------------
Donate comment here