Spring学习之(四)基于注解的组件扫描
本文是学习过程中的笔记内容,你们看了之后写出的代码都是BUG,不要怪我。哈哈哈~~
1、什么是组件扫描
1)、指定一个包路径,Spring会自动扫描改包及子包所有组件类,当发现组件类定义前有特定的注解标记时,就将该组件纳入到Spring容器。
2)、组件扫描可以替代大量的XML配置
<bean>
定义
2、指定扫描类路径
使用组件扫描,需要在
applicationContext.xml
文件配置中指定扫描类路径;在容器实例化时会自动进行扫描
- 如下代码示例:
<!-- 开启组件扫描后,会扫描指定包及其子包下的所有类 -->
<context:component-scan base-package="com.ohiambest"></context:component-scan>
3、自动扫描的注解标记
Spring容器并不是将配置到包中的所有类都进行加载。只有在组件前面有Spring的特定标记时,才会扫描到Spring的容器;
如下是注解标记列表
注解标记 | 描述 |
@Component | 通用注解 |
@Name | 通用注解 |
@Respository | 持久层注解 |
@Service | 业务层组件注解 |
@Controller | 控制层组件注解 |
4、自动扫描组件的命名
1)、当一个组件在扫描的过程中被检测到时,会生成一个默认的id值,默认id为小写开头的类名称。
2)、我们也可以通过注解标记,自定义id
默认的id采用类名的首字母小写,示例代码:
package com.ohiambest.service;
import org.springframework.stereotype.Service;
/**
* 将我们的类声明成一个service组件,spring会自动扫描到容器中<br/>
*
* 并且id的值为类名的小写开头:orderInfoService
*
* @author Administrator
*
*/
@Service
public class OrderInfoService {
}
如下我们给OrderInfoRepository
修改成自定义的id值
package com.ohiambest.dao;
import org.springframework.stereotype.Repository;
/**
*
* @author zhang_wei
*
*/
// 这里通过标记,修改默认的id名称
@Repository("orderInfoMapper")
public class OrderInfoRepository {
}
5、指定组件的作用域
1)、指定组件的作用域我们可以使用@Scope注解进行自定义
2)、在Spring中,被Spring管理的组件,默认的作用域都是singleton
如下示例,将作用域改为原型模式:
@Scope("prototype") // 修改作用域为原型模式
public class OrderInfoRepository {
}
6、初始化和销毁回调
复习:
1)、我们前面使用
xml
配置的方式可以指定类的初始化和销毁的回调方法,分别使用的是init-method
和destroy-method
2)、如果是容器级别的全局指定,则分别使用的是
default-init-method
和default-destroy-method
注解的方式指定初始化和销毁回调
3)、这里我们使用注解的方式来指定初始化和销毁的回调,分别使用
@PostConstruct
注解和@PreDestroy
指定初始化和销毁回调方法
6.1、代码
如下代码示例:
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
public class ExampleMessageBean {
@PostConstruct
public void init(){
System.out.println("ExampleMessageBean...init");
}
@PreDestroy
public void destroy(){
System.out.println("ExampleMessageBean...destroy");
}
}
6.2、测试
通过编写测试用例,我们可以发现控制台的输出内容如下:
测试用例的代码如下:
@Test
public void testScan(){
String config = "config/applicationContext-scan.xml";
AbstractApplicationContext context = new ClassPathXmlApplicationContext(config);
context.close();
}
7、指定注入依赖关系
具有依赖关系的Bean对象,利用下面任意一种注解都可以实现关系注入
- @Resource
- @
Autowired
/@Qualifier - @Inject/@Named
7.1、 @Resource注解
1)、@Resource 注解标记可以用在字段定义或者setter方法定义前面,默认首先按名称匹配注入,然后按类型匹配注入
2)、但是,当遇到多个匹配的Bean是注入会发生错误,可以显示的指定名称
例如:
@Resource(name="oracleUserDao")
示例代码:
@Resource(name="mySqlUserDao")
private UserDao userDao;
7.2、 @Autowired
/ @Qualifier 注解
1)、
@Autowired
注解标记一般用在Bean的属性及setter方法上,默认是按照类型进行注入的2)、一般数据库
Dao
层的注解,我们使用@Autowired
比较多3)、由于
@Autowired
默认是按照类型进行注入的,所以当遇到多个匹配的Bean时,会发生错误4)、因此,我们需要配合@Qualifier注解进行使用,效果和
@Resource(name="oracleUserDao")
一样
示例代码:
@Autowired
@Qualifier("mySqlUserDao")
private UserDao userDao;
7.3 、@Inject / @Named 注解
1)、@Inject 注解标记是Spring 3.0开始新增的对JSR-330标准的支持,使用前需要添加JSR-330的jar包,使用的方法同
@Autowired
相似2)、@Inject当遇到多个相同类型的Bean时,也会报错,这时需要使用@Named来进行指定
pom.xml中需要引入相关的jar包
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
示例代码如下:
//@Inject
private UserDao userDao;
@Inject
public void setUserDao(@Named("mySqlUserDao")UserDao userDao) {
this.userDao = userDao;
}
8、注入Spring的表达式
1)、使用@Value注解可以注入Spring表达式的值,
2)、使用Spring的表达式,我们需要在XML文件中配置指定要注入的properties文件
3)、Spring的表达式有一个专门的
SPEL
表达式语言进行支持我们这里以
JDBCDataSource
为例进行演示:
db.properties
的内容如下:
driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:xe
user=david
password=qwer1234
JDBCDataSource
的代码如下配置:
package com.ohiamcool.util;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* 数据库连接工具类
*
* @author zhang_wei
*
*/
@Component
public class JDBCDataSource implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private String driver;
@Value("#{dbProps.url}")
private String url;
@Value("#{dbProps.user}")
private String user;
@Value("#{dbProps.password}")
private String password;
public String getDriver() {
return driver;
}
@Value("#{dbProps.driver}")
public void setDriver(String driver) {
try {
Class.forName(driver);
this.driver = driver;
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public Connection getConnecttion() throws SQLException{
Connection connection = DriverManager.getConnection(url, user, password);
return connection;
}
public void colse(Connection conn){
if(conn !=null) {
try {
conn.close();
} catch (Exception e) {
}
}
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
spring的配置文件如下:
<context:component-scan base-package="com.ohiamcool"></context:component-scan>
<!-- 引用配置文件 -->
<util:properties id="dbProps" location="classpath:config/db.properties"/>
8.1、编写测试用例:
这里通过编写测试用例测试我们的自动注入的结果
@Test
public void testConfig() throws Exception{
String configLocation = "config/applicationContext-scan.xml";
AbstractApplicationContext context = new ClassPathXmlApplicationContext(configLocation);
JDBCDataSource dataSource = context.getBean(JDBCDataSource.class);
System.out.println(dataSource);
Connection conn = dataSource.getConnecttion();
System.out.println(conn);
context.close();
}
运营测试用例之后的输出结果为如下图: