##一、注解的作用
组件扫描(component scanning): Spring 能够从 classpath 下自动扫描, 侦测和实例化具有特定注解的组件。
##二、特定的注解
@Component
: 基本注解, 标识了一个受 Spring 管理的组件@Respository
: 标识持久层组件@Service
: 标识服务层(业务层)组件@Controller
: 标识表现层组件
##三、示例代码(以MVC设计模式为例)
###1.持久层(Respository,也可以说是Model层)代码
####(1)新建一个名为top.cheungchingyin.beans.annotation.repository
包
注意!!
持久层(Respository)的代码全在该包内创建
####(2)创建一个名为UserRepository
的接口,代码如下
package top.cheungchingyin.beans.annotation.repository;
public interface UserRepository {
void save();
}
####(3)创建一个名为UserRepositoryImpl
的Java类,实现UserRepository
接口
package top.cheungchingyin.beans.annotation.repository;
import org.springframework.stereotype.Repository;
@Repository("userRepository")
public class UserRepositoryImpl implements UserRepository {
@Override
public void save() {
System.out.println("UserRepository save...");
}
}
注解@Repository("userRepository")
括号中的内容是为了设置bean的名字(即value
属性),如果不指定,当spring扫描到的时候会以使用非限定类名, 第一个字母小写,即如果类名是UserRepositoryImpl
,bean的名字则是userRepositoryImpl
。
###2.服务层(Service)代码
####(1)创建一个名为top.cheungchingyin.beans.annotation.service
的包。
注意!!
持久层(Service)的代码全在该包内创建
####(2)创建一个名为UserService
的Java类
package top.cheungchingyin.beans.annotation.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import top.cheungchingyin.beans.annotation.repository.UserRepository;
@Service
public class UserService {
@Autowired
@Qualifier("userRepository")//由于在UserRepository有两个实现类,不知道区分哪一个,所以需要@Qualifier指明是哪一个类
private UserRepository userRepository;
public void add() {
System.out.println("UserService Add...");
userRepository.save();
}
}
注解 | 说明 |
---|---|
@Service | 表示该类为Service层的代码,让spring能够扫描识别出来放进IOC容器中 |
@Autowired | 用于bean的自动注入,此处用于userRepository的自动注入 |
@Qualifier | 中文叫做“合格者”,用于当某个接口有多个实现类的时候指明是使用哪一个类。如果没有此标签,spring可能检测到与两个实现类而不知需要注入哪一个类而报错 |
###3.视图层(View,此处用controller层代替)代码
####(1)创建一个名为top.cheungchingyin.beans.annotation.controller
的包
注意!!
视图层(View,此处用controller层代替)的代码全在该包内创建
####(2)创建一个名为UserController
的Java类
package top.cheungchingyin.beans.annotation.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import top.cheungchingyin.beans.annotation.service.UserService;
@Controller
public class UserController {
@Autowired
private UserService userService;
public void execute() {
System.out.println("UserController execute...");
userService.add();
}
}
此处使用@Controller
注解来表示该类属于表现层的类。
由于UserService
没有其他实现类,所以只需要使用@Autowired
进行bean自动注入,而不用使用@Qualifier
来指明哪一个bean。
###4.在src根目录下创建一个bean的配置文件beans-annotation.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 http://www.springframework.org/schema/context/spring-context-4.1.xsd">
<!-- 指定SpringIOC容器扫描的包 -->
<!-- 可以指定resource-pattern指定扫描的资源 -->
<context:component-scan base-package="top.cheungchingyin.beans.annotation" ></context:component-scan>
</beans>
注意!!
base-package
属性指定一个需要扫描的基类包,Spring 容器将会扫描这个基类包里及其子包中的所有类. 。- 当需要扫描多个包时, 可以使用逗号分隔。
- 如果仅希望扫描特定的类而非基包下的所有类,可使用
resource-pattern
属性过滤。
在标签<context:component-scan></context:component-scan>
里面可以使用以下子节点进行过滤不想被IOC容器扫描的类。
<context:include-filter>
:包含那些表达式的组件,该子节点需要use-default-filters
配合使用<context:exclude-filter>
:指定排除那些指定表达式的组件
如果type
填的是 annotation,则expression
填注解的全类名
如果type
填的是assignable,则expression
填的是类的全类名,表示该类及该类的子类都不包括
例如
<context:component-scan base-package="com.spring.annotation">
<context:exclude-filter type="annotation"expression="org.springframework.stereotype.Repository"/></context:component-scan>
<context:include-filter>
和<context:exclude-filter>
子节点支持多种类型的过滤表达式
###5.用于测试的主类main.java
package top.cheungchingyin.beans.annotation;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import top.cheungchingyin.beans.annotation.controller.UserController;
public class Main {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-annotation.xml");
UserController userController = (UserController) ctx.getBean("userController");
userController.execute();
}
}
测试结果
##四、总结
@Autowired
注解自动装配具有兼容类型的单个 Bean属性
-
构造器, 普通字段(即使是非 public), 一切具有参数的方法都可以应用@Authwired 注解。
-
默认情况下, 所有使用
@Authwired
注解的属性都需要被设置. 当 Spring 找不到匹配的 Bean 装配属性时, 会抛出异常, 若某一属性允许不被设置, 可以设置@Authwired
注解的required
属性为false
。 -
默认情况下, 当 IOC 容器里存在多个类型兼容的 Bean 时, 通过类型的自动装配将无法工作. 此时可以在
@Qualifier
注解里提供 Bean 的名称. Spring 允许对方法的入参标注@Qualifiter
已指定注入 Bean 的名称。 -
@Authwired
注解也可以应用在数组类型的属性上, 此时 Spring 将会把所有匹配的 Bean 进行自动装配。 -
@Authwired
注解也可以应用在集合属性上, 此时 Spring 读取该集合的类型信息, 然后自动装配所有与之兼容的 Bean。 -
@Authwired
注解用在java.util.Map
上时, 若该Map
的键值为 String, 那么 Spring 将自动装配与之 Map 值类型兼容的 Bean, 此时 Bean 的名称作为键值