对于
DI
使用注解,将不再需要在
Spring
配置文件中声明
bean
实例。
Spring
中使用注解,
需要在原有
Spring
运行环境基础上再做一些改变。
项目结构
需要在
Spring
配置文件中配置组件扫描器,用于在指定的基本包中扫描注解。
指定多个包的方式三种方式,
(1)使用多个context:component-scan指定不同的包的路径
(2)使用base-package的值,使用分隔符
分隔符可以是 逗号(,)分号(;)还可以使用空格,不建议使用空格。
逗号分隔:
分号分隔
(3)base-package是指定到父包名
base- package的值表是基本包,容器启动会自动扫描包,及其子包中的注解,当然也会扫描到子包下级的子包。所以base-package可以指定一个父包就可以。
整个applicationContext.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: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.it.bao1"/>-->
<!-- <context:component-scan base-package="com.it.bao3"/>-->
<!-- <context:component-scan base-package="com.it.bao5"/>-->
<!-- <context:component-scan base-package="com.it.bao6"/>-->
<!-- 指定多个包的三种方式-->
<!-- 第一种-->
<!-- <context:component-scan base-package="com.it.bao1"/>-->
<!-- <context:component-scan base-package="com.it.bao2"/>-->
<!--第二种-->
<!-- <context:component-scan base-package="com.it.bao1,com.it.bao3"/>-->
<!-- <context:component-scan base-package="com.it.bao1;com.it.bao2"/>-->
<!-- 第三种-->
<!-- <context:component-scan base-package="com.it"/>-->
</beans>
applicationContext.xml文件有了组件扫描器,就可以对该组件扫描器所指定包下的类文件进行注解配置。
2.4.1
定义
Bean
的注解
@Component
需要在类上使用注解
@Component
,该注解的
value
属性用于指定该
bean
的
id
值。@Component
不指定
value
属性,
bean
的
id
是类名的首字母小写。
另外,
Spring
还提供了
3
个创建对象的注解:
@Repository
用于对
DAO
实现类进行注解
@Service
用于对
Service
实现类进行注解
@Controller
用于对
Controller
实现类进行注解
这三个注解与
@Component
都可以创建对象,但这三个注解还有其他的含义,
@Service创建业务层对象,业务层对象可以加入事务功能,
@Controller
注解创建的对象可以作为处
理器接收用户的请求。
@Repository
,
@Service
,
@Controller
是对
@Component
注解的细化,标注不同层的对象。即持久层对象,业务层对象,控制层对象。
2.4.2
简单类型属性注入
@Value
需要在属性上使用注解
@Value
,该注解的
value
属性用于指定要注入的值。
使用该注解完成属性注入时,类中无需
setter
。当然,若属性有
setter
,则也可将其加到
setter
上。
结合:组件扫描器, 定义 Bean 的注解@Component,简单类型属性注入@Value三种方式的第一个练习
1.创建Student
package com.it.bao1;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
//该注解是用来创建对象的,等同于<bean>的功能
//value就是对象的名称,等同于<bean>中的id值
//spring容器中的对象遵循单例原则,创建的对象的名字是唯一的。
//component注解写在类的上面
//省略value时
//@Component("myStudent")
//使用value时
@Component(value = "myStudent")
//不指定对象名称,由spring提供默认名称
//@Component
public class Student {
/**
* @value简单类型的属性赋值
*属性:value是String类型的,表示简单类型的属性值
* 位置:1.在属性定义的上方,无需set方法,推荐使用
* 2.在set方法的上方,用到了set方法
*/
@Value(value = "小红")
private String name;
@Value(value = "22")
private int age;
public Student() {
System.out.println("调用student无参数构造方法");
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
2.创建spring的配置文件applicationContext.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: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.it.bao1"/>
<!-- <context:component-scan base-package="com.it.bao3"/>-->
<!-- <context:component-scan base-package="com.it.bao5"/>-->
<!-- <context:component-scan base-package="com.it.bao6"/>-->
<!-- 指定多个包的三种方式-->
<!-- 第一种-->
<!-- <context:component-scan base-package="com.it.bao1"/>-->
<!-- <context:component-scan base-package="com.it.bao2"/>-->
<!--第二种-->
<!-- <context:component-scan base-package="com.it.bao1,com.it.bao3"/>-->
<!-- <context:component-scan base-package="com.it.bao1;com.it.bao2"/>-->
<!-- 第三种-->
<!-- <context:component-scan base-package="com.it"/>-->
</beans>
3.创建测试文件
package com.it;
import static org.junit.Assert.assertTrue;
import com.it.bao1.Student;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Unit test for simple App.
*/
public class AppTest
{
@Test
public void test1(){
String config="applicationContext.xml";
ApplicationContext ac=new ClassPathXmlApplicationContext(config);
Student student = (Student) ac.getBean("myStudent");
System.out.println(student);
}
}
4.结果展示
2.4.3 byType 自动注入@Autowired
需要在引用属性上使用注解
@Autowired
,该注解默认使用
按类型自动装配
Bean
的方式。
使用该注解完成属性注入时,类中无需
setter
。当然,若属性有
setter
,则也可将其加
到
setter
上。
测试:
1.创建School类
package com.it.bao3;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component(value = "mySchool")
public class School {
@Value(value = "清华大学")
private String name;
@Value(value = "中国北京")
private String address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "School{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
}
2.创建Student类
package com.it.bao3;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
//该注解是用来创建对象的,等同于<bean>的功能
//value就是对象的名称,等同于<bean>中的id值
//spring容器中的对象遵循单例原则,创建的对象的名字是唯一的。
//component注解写在类的上面
//省略value时
//@Component("myStudent")
//使用value时
@Component(value = "myStudent")
//不指定对象名称,由spring提供默认名称
//@Component
public class Student {
/**
* @value简单类型的属性赋值
*属性:value是String类型的,表示简单类型的属性值
* 位置:1.在属性定义的上方,无需set方法,推荐使用
* 2.在set方法的上方,用到了set方法
*/
@Value(value = "小红")
private String name;
@Value(value = "22")
private int age;
/**
* 引用类型的赋值
* @AutoWired:这是spring框架提供的注解,实现引用类型的赋值
*使用的是自动注入原则,支持byName,byType
* 默认使用的是byType的自动注入
* 位置:1.在属性定义的上方,无需set方法,推荐使用
* 2.在set方法的上方,用到了set方法
*/
@Autowired
private School school;
public Student() {
System.out.println("调用student无参数构造方法");
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", school=" + school +
'}';
}
}
3.创建applicationContext.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: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.it.bao1"/>-->
<context:component-scan base-package="com.it.bao3"/>
<!-- <context:component-scan base-package="com.it.bao5"/>-->
<!-- <context:component-scan base-package="com.it.bao6"/>-->
<!-- 指定多个包的三种方式-->
<!-- 第一种-->
<!-- <context:component-scan base-package="com.it.bao1"/>-->
<!-- <context:component-scan base-package="com.it.bao2"/>-->
<!--第二种-->
<!-- <context:component-scan base-package="com.it.bao1,com.it.bao3"/>-->
<!-- <context:component-scan base-package="com.it.bao1;com.it.bao2"/>-->
<!-- 第三种-->
<!-- <context:component-scan base-package="com.it"/>-->
</beans>
4.创建测试类
package com.it;
import com.it.bao3.Student;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Unit test for simple App.
*/
public class AppTest3
{
@Test
public void test1(){
String config="applicationContext.xml";
ApplicationContext ac=new ClassPathXmlApplicationContext(config);
Student student = (Student) ac.getBean("myStudent");
System.out.println(student);
}
}
结果
2.4.4 byName 自动注入@Autowired 与@Qualifier
需要在引用属性上联合使用注解
@Autowired
与
@Qualifier
。
@Qualifier
的
value
属性用于指定要匹配的
Bean
的
id
值。类中无需
set
方法,也可加到
set
方法上。
测试:
1.创建School类
同上
2.创建Student类
package com.it.bao3;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
//该注解是用来创建对象的,等同于<bean>的功能
//value就是对象的名称,等同于<bean>中的id值
//spring容器中的对象遵循单例原则,创建的对象的名字是唯一的。
//component注解写在类的上面
//省略value时
//@Component("myStudent")
//使用value时
@Component(value = "myStudent")
//不指定对象名称,由spring提供默认名称
//@Component
public class Student {
/**
* @value简单类型的属性赋值
*属性:value是String类型的,表示简单类型的属性值
* 位置:1.在属性定义的上方,无需set方法,推荐使用
* 2.在set方法的上方,用到了set方法
*/
@Value(value = "小红")
private String name;
@Value(value = "22")
private int age;
/**
* 引用类型的赋值
* @AutoWired:这是spring框架提供的注解,实现引用类型的赋值
*使用的是自动注入原则,支持byName,byType
* 默认使用的是byType的自动注入
* 位置:1.在属性定义的上方,无需set方法,推荐使用
* 2.在set方法的上方,用到了set方法
*/
// @Autowired
// 通过byName自动注入
@Autowired
@Qualifier(value = "mySchool")
private School school;
public Student() {
System.out.println("调用student无参数构造方法");
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", school=" + school +
'}';
}
}
3.创建applicationContext.xml配置文件
同上
4.创建测试类
同上
结果
同上
@Autowired
还有一个属性
required
,默认值为
true
,表示当匹配失败后,会终止程序运行。若将其值设置为
false
,则匹配失败,将被忽略,未匹配的属性值为
null
。
2.4.5 JDK
注解
@Resource
自动注入
spring提供了对jdk中@resource注解的支持。
@Resource
注解既可以按名称匹配
Bean
,也可以按类型匹配
Bean
。
默认是按名称注入
。使用该注解,要求
JDK
必须是
6
及以上版本。
@Resource
可在属性上,也可在
set
方法上。
(
1
)
byType
注入引用类型属性
@Resource
注解若不带任何参数,采用
默认按名称
的方式注入,按名称不能注入
bean
,则会按照类型进行
Bean
的匹配注入。
(2) byName 注入引用类型属性
@Resource 注解指定其 name 属性,则 name 的值即为按照名称进行匹配的 Bean 的 id。