完全使用注解实现 IOC
通过使用注解的方式,可以更方便的将我们自己创建的对象放入到 Spring bean 容器中,我们这里介绍使用纯注解的方式实现 IOC,并且主要介绍替代.xml
文件配置的过程,虽然这种方式对于包装好的对象使用起来有些麻烦
准备
首先我们需要准备一个.java
的配置文件,用于取代bean.xml
,我们将它建在com
的父目录java
中的config
包下,取名为SpringConfiguration.java
思路
既然说是取代,那这个类就要通过注解的方式,实现原本使用bean.xml
配置 IOC 时的全部功能,我们先来看看之前使用注解和bean.xml
结合配置 IOC 时的bean.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.xsd">
<context:component-scan base-package="com.lmh"/>
<!-- 配置 QueryRunner 对象 -->
<bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
<constructor-arg name="ds" ref="dataSource"/>
</bean>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.cj.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring?useSSL=false&serverTimezone=UTC"/>
<property name="user" value="root"/>
<property name="password" value="lmh12358"/>
</bean>
</beans>
下面,我们就根据 xml 文件所提供的功能,一个一个转化为注解实现
定义配置类(@Configuration)
配置类config.SpringConfiguration.java
我们已经创建好了,我们需要使用@Configuration
来说明它是一个配置类如下:
@Configuration
public class SpringConfiguration {
}
指定注解存在的位置(@ComponentScan)
随后,在bean.xml
中有<context:component-scan base-package="com.lmh"/>
这样一句话,它是说明在我们的项目中需要被扫描的使用注解的位置,我们在配置类中使用@ComponentScans
注解实现这一功能
@ComponentScans
注解用来指定 Spring 在创建容器所扫描的包,它里边需要使用@ComponentScan
注解来指定包名,使用方法如下:
@ComponentScans(
@ComponentScan(basePackages = {"com.lmh", ...})
)
通过这种方式可以指定需要扫描的包名,basePackages
是一个数组,可以包含多个包名
使用注解将外部类放入容器(@Bean)
以上的功能只能将我们自己的对象存入到 Spring 容器中,那如果是像QueryRunner
这样的对象呢
这是需要使用@Bean
注解,@Bean
注解用来修饰一个方法,可以把当前方法的返回值作为 bean 对象存入 Spring 的 IOC 容器中,name
属性即为该 bean 的id
,并且我们可以使用@Scope
等注解来修饰它,使用如下
@Bean(name = "runner")
@Scope("prototype")
public QueryRunner createQueryRunner(DataSource dataSource) {
return new QueryRunner(dataSource);
}
@Bean(name = "dataSource")
public DataSource createDataSource() throws PropertyVetoException {
ComboPooledDataSource ds = new ComboPooledDataSource();
ds.setDriverClass(driver);
ds.setJdbcUrl(url);
ds.setUser(username);
ds.setPassword(password);
return ds;
}
我们可以看到,QueryRunner
对象是需要使用DataSource
类型的对象作为参数来创建的,这是就需要为这个 bean 注入DataSource dataSource
,此时我们只需要定义一个id
和参数名相同的bean
即可,即使用注解配置方法时,如果方法有参数,Spring 框架会去容器中查找有没有可用的 bean,查找方式和 AutoWired 相同
其他一些常用注解
@Import
@Import
注解用来定义子配置文件,假设我们要在JdbcConfig.java
中配置 JDBC 连接信息,就可以通过在父配置类中使用@Import
注解:
@Import(value = {
JdbcConfig.class
})
@PropertySources、@Value
@PropertySources
注解用来指定.properties
的配置文件,@Value
用来调用配置文件中的值,通过这两个注解,我们可以调用配置文件的信息,例如将 JDBC 连接包装在配置文件中我们可这样使用
配置文件:
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring?useSSL=false&serverTimezone=UTC
jdbc.username=root
jdbc.password=lmh12358
JdbcConfig.java
package config;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.commons.dbutils.QueryRunner;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.*;
import javax.sql.DataSource;
import java.beans.PropertyVetoException;
@PropertySources(
@PropertySource("classpath:jdbcConfig.properties")
)
public class JdbcConfig {
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
/**
* 用于创建一个 QueryRunner 对象
* @param dataSource
* @return
*/
@Bean(name = "runner")
@Scope("prototype")
public QueryRunner createQueryRunner(DataSource dataSource) {
return new QueryRunner(dataSource);
}
@Bean(name = "dataSource")
public DataSource createDataSource() throws PropertyVetoException {
ComboPooledDataSource ds = new ComboPooledDataSource();
ds.setDriverClass(driver);
ds.setJdbcUrl(url);
ds.setUser(username);
ds.setPassword(password);
return ds;
}
}
测试
由于不再使用 XML 文件,我们调用 bean 工厂的方法就要有变化,我们通过一下语句来指定配置类
private ApplicationContext context;
@Before
public void init() {
context = new AnnotationConfigApplicationContext(SpringConfiguration.class);
}
这样我们就指定了SpringConfiguration.java
为配置类,并且还可以直接使用它内部使用的子配置类