暑期自学 Day 18 | Spring (四)
IoC 注解
使用注解创建对象之后,就不用像之前那样通过bean标签手动配置创建对象的属性了。
注解要写在需要注入的类或者成员方法前。
按作用分为四类:
创建对象
- 和 bean 标签功能一样
- @Component - 把当前对象存入 spring 容器
- 属性:value: 指定 bean 的 id,默认值是当前类名,但首字母要小写
- 衍生注解:使三层对象更加清晰,相当于@Component的子类
- @Controller:表现层
- @Service:业务层
- @Repository:持久层
在 bean.xml 中配置 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
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 配置 component 注解所需的标签 -->
<context:component-scan base-package="spring.selflearning"></context:component-scan>
</beans>
注入数据
- 和 property 功能一样
- @Autowired: 自动按照类型注入数据,只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配,就能注入成功。
- 可以出现在变量上,也可以出现在方法上。
- 此时无需set方法
- @Qualifier:按照类型注入的基础上再按照名称注入。给类成员注入时不能单独使用,给方法参数注入时可以。
- @Value:注入基本类型和String类型
- 集合类型注入只能通过xml实现
- 改变作用范围
- 和 scope 一样
- @Scope,取值可以是 singleton 或 prototype
- 生命周期相关
- 和 init-method 和 destroy-method 作用一样
- @PreDestroy 销毁
- @PostConstruct 初始化
- 需要用 close() 方法释放容器
- 只能销毁单例对象
Spring 的一些新注解
这些新注解功能和bean.xml中的一些属性功能相同,为的是取代bean.xml中的配置方式。
@Configuration
- 表示当前类是个配置类
- 当配置类作为AnnotationConfigApplicationContext对象创建的参数时,该注解可以不写。
如某个方法中使用ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
创建对象,那么无需在方法上使用@Configuration注解,因为Java会自动找到SpringConfiguration.class
这个配置类创建对象。
AnnotationConfigApplicationContext
方法中可以写多个配置类,用逗号分隔。
@ComponentScan
- 指定spring创建容器时需要扫描的包;属性:basePackages
- 功能和
<context:component-scan base-package="spring.selflearning"></context:component-scan>
一样。
@Bean
- 把当前方法的返回值作为bean对象存入ioc容器中;属性:name,指定bean的id,不写时默认值为当前方法的名称
- 如果bean注解有值,spring会去容器中查找是否有可用的bean对象,查找方式和AutoWired注解的功能一样
如给创建一个QueryRunner对象的方法添加注解:
@Bean(name = "runner")
@Scope("prototype")
public QueryRunner createQueryRunner(DataSource dataSource) {
return new QueryRunner(dataSource);
}
@Import
- 指定其他配置类的字节码
- 使用Import注解之后的类就是父配置类,导入的是子配置类。此时创建对象时只需注解父类配置类即可。
PropertySource
- 用于指定properties的位置
- @Value:指定文件路径和名称,classpath,表示在类路径下
- 在我实际使用中,发现Value注解无法正常读取properties配置文件,目前这个问题还没解决。附自己的代码:
父配置类:SpringConfiguration.java
@ComponentScan(basePackages = "spring.selflearning") // 属性是数组类型,如果需要扫描多个类则需加大括号
@Import(JdbcConfig.class)
@PropertySource("classpath:jdbcConfig.properties")
public class SpringConfiguration {}
子配置类: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.Bean;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.sql.DataSource;
@Component("jdbcConfig")
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;
public String getDriver() {
return driver;
}
public String getUrl() {
return url;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
@Bean(name = "runner")
@Scope("prototype")
public QueryRunner createQueryRunner(DataSource dataSource) {
return new QueryRunner(dataSource);
}
@Bean(name = "dataSource")
public DataSource createDataSource() {
try {
ComboPooledDataSource ds = new ComboPooledDataSource();
ds.setDriverClass(driver);
ds.setJdbcUrl(url);
ds.setUser(username);
ds.setPassword(password);
return ds;
}
catch(Exception e) {
throw new RuntimeException(e);
}
}
}
jdbcConfig.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/eesy
jdbc.username=root
jdbc.password=1234
关于何时使用 xml,何时使用注解
实际上注解并不总是能减少配置过程中的代码量,如配置JDBC连接时。
配置注入的对象在别人写好的类中,那么使用xml更好;如果是自己写的类,直接在类中添加注解则更为方便。
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: