组件扫描(component scanning): Spring 能够从 classpath 下自动扫描, 侦测和实例化具有特定注解的组件.
特定组件包括:
@Component: 基本注解, 标识了一个受 Spring 管理的组件
@Respository: 标识持久层组件
@Service: 标识服务层(业务层)组件
@Controller: 标识表现层组件
对于扫描到的组件, Spring 有默认的命名策略: 使用非限定类名, 第一个字母小写. 也可以在注解中通过 value 属性值标识组件的名称
特定的组件注入:
@Autowired:注解自动装配具有兼容类型的单个 Bean属性
@Resource:(这个注解属于J2EE的),默认按照名称进行装配
步骤:
1.加入context命名空间
2.开启扫描
3. 在类上使用以上四个组件注解
以下实例仅仅是为了演示注解,跟业务无关。
1.pom.xml依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>spring-8</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.2.13.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.2.13.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.13.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>5.2.13.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
2.spring的配置文件
<?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="com.qwy"/>
</beans>
3.POJO
package com.qwy.bean;
/**
* @author qwy
* @create 2021-04-22 19:35
**/
public class Users {
}
4. DAO接口
package com.qwy.dao;
import com.qwy.bean.Users;
/**持久层接口
* @author qwy
* @create 2021-04-22 19:37
**/
public interface UsersDAO {
//添加用户
public int save(Users users);
//其他持久层方法
}
5.DAO接口实现类
package com.qwy.dao.impl;
import com.qwy.bean.Users;
import com.qwy.dao.UsersDAO;
import org.springframework.stereotype.Repository;
/**持久层实现类
* @author qwy
* @create 2021-04-22 19:38
* @Repository :将实现类交给spring容器管理
* value: 指定实例名称,默认为类名首字母小写
**/
@Repository(value = "usersDAO")
public class UsersDAOImpl implements UsersDAO {
public int save(Users users) {
System.out.println("UsersDAOImpl.save");
return 0;
}
}
6.service接口
package com.qwy.service;
import com.qwy.bean.Users;
/**
* @author qwy
* @create 2021-04-22 19:35
**/
public interface UsersService {
//添加用户
public int save(Users users);
//其他方法
}
7. service接口实现类
package com.qwy.service.impl;
import com.qwy.bean.Users;
import com.qwy.dao.UsersDAO;
import com.qwy.service.UsersService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @author qwy
* @create 2021-04-22 19:36
* @Service :将该类交给spring管理
* value:给该实例起名,默认为类名首字母小写
*
*
**/
@Service(value = "usersService")
public class UsersServiceImpl implements UsersService {
@Autowired
private UsersDAO usersDAO;
public int save(Users users) {
usersDAO.save(users);
System.out.println("UsersServiceImpl.save");
return 0;
}
}
8.控制层
package com.qwy.controller;
import com.qwy.bean.Users;
import com.qwy.service.UsersService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
/**
* @author qwy
* @create 2021-04-22 19:43
* @Controller :将该类交给spring容器
**/
@Controller
public class UsersController {
//注入UsersServiceImpl的实例
@Autowired
private UsersService usersService;
public String save(Users users){
usersService.save(users);
System.out.println("UsersController.save");
return "hello";
}
}
9.测试类
package com.qwy.test;
import com.qwy.bean.Users;
import com.qwy.controller.UsersController;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author qwy
* @create 2021-04-22 19:45
**/
public class TestAnnotation {
private ApplicationContext ac= new ClassPathXmlApplicationContext("applicationContext.xml");
@Test
public void test1(){
UsersController usersController = ac.getBean("usersController", UsersController.class);
usersController.save(new Users());
}
}
执行结果:
UsersDAOImpl.save
UsersServiceImpl.save
UsersController.save
通过执行结果发现。DAO,Service,Controller已经交给spring管理(IOC),依赖的对象也已经注入(DI).
10.补充
1
<context:component-scan base-package=“com.qwy”/>
base-package 属性指定一个需要扫描的基类包,Spring 容器将会扫描这个基类包里及其子包中的所有类.
当需要扫描多个包时, 可以使用逗号分隔.
如果仅希望扫描特定的类而非基包下的所有类,可使用 resource-pattern 属性过滤特定的类,示例:
<context:component-scan base-package=“com.qwy” resource-pattern=“controller/*.class”/>
另外:
context:include-filter 子节点表示要包含的目标类
context:exclude-filter 子节点表示要排除在外的目标类
context:component-scan 下可以拥有若干个 context:include-filter 和 context:exclude-filter 子节点
2
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 的名称作为键值。
Spring 还支持 @Resource 和 @Inject 注解,这两个注解和 @Autowired 注解的功用类似
@Resource 注解要求提供一个 Bean 名称的属性,若该属性为空,则自动采用标注处的变量或方法名作为 Bean 的名称
@Inject 和 @Autowired 注解一样也是按类型匹配注入的 Bean, 但没有 reqired 属性
建议使用 @Autowired 注解