从 Spring 2.5 开始就可以使用注解来配置依赖注入。使用注解的方式使我们无需在XML中配置一个Bean引用,更加简单和方便。但注解配置默认情况下在Spring中是关闭的,我们需要在配置文件中开启他,使用在之前的bean约束中加入xmlns:context
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!--告知spring在创建容器时要扫描的包,配置所需要的标签不是在beans的约束中,而是一个名称为context名称空间和约束中 xmlns:context-->
<context:component-scan base-package="com.lb"></context:component-scan>
</beans>
用于创建对象的: 作用与在XML配置中编写一个bean标签实现的功能是一样的
- @Component: 作用:用于把当前对象存入spring容器中,属性 value:指定id,默认为类名首字母小写
还有三个作用与Component相同的注解, @Controller:一般用于表现层,@Service: 一般用于业务层,@Repository:一般用于持久层,这三个是spring为三层架构提供的注解
用于注入数据的: 作用与在XML配置中ean标签中的property标签的作用是一样的实现的功能是一样的
- @ Autowired: 自动按照类型注入,只要容器中有唯一的一个bean对象类型和注入的变量类型匹配,如果没有匹配,则报错,就可以注入成功出现的位置可以是变量上,也可以是方法上
- @ Qualifier: 在按照类中注入的基础之上再按照名称注入,它在给类成员注入时不能单独使用
例子:当有两个类都是继承了IAccountDao,只使用 @ Autowired ,spring无法知道要注入哪一个类,所有会报错
此时就需要到上 @ Qualifier 指定bean的id
还要一个注解是 @ Resource 直接按照bean的id注入,属性name:用于指定bean的id,但是它不属于spring的注解,而是javax.annotation.Resource
以上注解都只能注入其他bean类型的数据,而基本数据类型和String类型无法使用以上注解注入,集合类型的注入只能通过xml实现
- @ value: 用于注入基本数据类型和String类型,属性value用于指定数据的值,可使用spEL
下面通过完成简单的增删改查来感受下使用bean.xml和使用注解的差别
使用bean.xml
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<!--dbutils-->
<dependency>
<groupId>commons-dbutils</groupId>
<artifactId>commons-dbutils</artifactId>
<version>1.6</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.15</version>
</dependency>
<!--c3p0-->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--配置service-->
<bean id="accountService" class="com.lb.service.impl.AccountServiceImpl">
<!--注入Dao-->
<property name="accountDao" ref="accountDao"/>
</bean>
<!--配置Dao层-->
<bean id="accountDao" class="com.lb.dao.impl.AccountDaoImpl">
<!--注入runner-->
<property name="runner" ref="runner"/>
</bean>
<bean id="runner" class="org.apache.commons.dbutils.QueryRunner">
<!--注入dataSource-->
<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?serverTimezone=GMT%2B8"/>
<property name="user" value="root"/>
<property name="password" value="1001101"/>
</bean>
</beans>
使用配置文件的是通过set方法注入
使用注解
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
https://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.lb"/>
<bean id="runner" class="org.apache.commons.dbutils.QueryRunner">
<!--注入dataSource-->
<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?serverTimezone=GMT%2B8"/>
<property name="user" value="root"/>
<property name="password" value="1001101"/>
</bean>
</beans>
可以看出使用注解以后,配置文件变得简化了,也不需要使用set方法来注入,但还是没能完成脱离配置文件
完整的测试代码在我的GitHub中,链接在文末,这里只展示出重点
其他注解
在上面的例子可以看到,所有使用了注解,但还是没有完全脱离配置文件,在spring中,我们可以使用**@Configuration** 来标注一个类为配置类,该配置类的作用与bean.xml相同,可以代替bean.xml
- @ComponentScan:指定spring在创建容器时是要扫描的包,此注解与<context:component-scan base-package=“包名”/>相同
- @Bean: 用于把当前方法的返回值作为bean对象存入到spring的IOC容器中,属性:name,用于指定bean的id,默认为当前方法的类名,当使用注解配置方法时,如果方法有参数,spring框架会去容器中查找有没有可用的bean对象,查找的方式和autowired注解的作用一样
@Bean
public QueryRunner createRunner(DataSource dataSources){
return new QueryRunner(dataSources);
}
@Bean
public DataSource createDataSource(){
try {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass(driver);
dataSource.setJdbcUrl(url);
dataSource.setUser(username);
dataSource.setPassword(password);
return dataSource;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
- @import: 用于导入其他配置类,属性:value,用于指定其他配置类的字节码,有import注解的类是主配置类,被导入的类是子配置类
像上图一样,我们在配置数据库的时候,常常会把数据库写在properties文件中,然后再在程序中引用 @PropertySource: 用于指定properties文件的位置 classpath: 类路径,可以配合@value来 使用