经过前一篇的案例,我们发现不管是xml还是注解方式,都还会有Spring的配置文件bean.xml,该文件可以通过本节讲解的注解进行去除。
现在bean.xml中还有两部分内容,一是要告知Spring要扫描的包,二是要配置runner和DataSource
注解
@Configuration
作用:用于指定当前类是一个 spring 配置类(相当于Spring配置文件bean.xml), 当创建容器时会从该类上加 载注解。 获取容器时需要使用AnnotationApplicationContext(有@Configuration 注解的类.class) 属性: value:用于指定配置类的字节码
@Configuration
public class SpringConfiguration { }
注意:当配置类作为AnnotationConfigApplicationContext对象创建的参数时,该注解可以不写。
如:new AnnotationConfigApplicationContext(SpringConfig.class);
此时SpringConfig.class作为参数,那么SpringConfig类上的@Configuration注解可以不写
@ComponentScan
作用:用于指定 spring 在初始化容器时要扫描的包。 作用和在 spring 的 xml 配置文件中的:
是一样的。 属性: basePackages:用于指定要扫描的包。和该注解中的 value 属性作用一样
value:和basePackages作用一样。
两个属性写哪个都可以,作用一致
//这两个注解就可以将bean.xml中的扫描包配置去掉
@Configuration //代表spring 的配置类,相当于 bean.xml 文件
@ComponentScan("com.mg") //指定扫描的包
public class SpringConfiguration { }
@Bean
作用:该注解只能写在方法上,把当前方法的返回值作为bean对象存入Spring的IOC容器 属性: name:用于指定 bean 的 id,不写时默认是当前方法名称
@Configuration
@ComponentScan(basePackages = "com.mg")
public class SpringConfig {
//配置DataSource
@Bean(name="dataSource")
public DataSource createDataSource() {
try {
ComboPooledDataSource ds = new ComboPooledDataSource();
ds.setUser("root");
ds.setPassword("root");
ds.setDriverClass("com.mysql.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql://localhost:3306/spring");
return ds;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//配置queryRunner
@Bean(name = "queryRunner")
@Scope("prototype")
public QueryRunner createQueryRunner(DataSource dataSource) {
return new QueryRunner(dataSource);
}
}
细节:当使用注解配置方法时,如果方法有参数,spring回去容器中查找有无可用的bean对象,查找方式和
Autowired注解一致,所以写createQueryRunner方法时,如果没有先定义DataSource则此处会报红。
如果存在多个对象可以使用@Qualifier指定使用哪一个
此时用以上几个注解就可以将Spring的配置文件移除了。
测试使用:要注意使用AnnotationConfigApplicationContext这个类
@Test
public void test2() {
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
IAccountService accountService = ac.getBean("accountService", IAccountService.class);
List<Account> accounts = accountService.findAllAccount();
for(Account account:accounts) {
System.out.println(account);
}
}
注意:
new AnnotationConfigApplicationContext(SpringConfig.class);此处的参数要写配置类,可以写多个。
此时SpringConfig.class作为参数,那么SpringConfig类上的@Configuration注解可以不写
@Import
作用:用于导入其他配置类。引入的其他配置类可以不用再写@Configuration 注解。 当然写上也没问题。 属性: value[]:用于指定其他配置类的字节码。
//主配置类
@Configuration
@ComponentScan(basePackages = "com.mg")
@Import(JdbcConfig.class)//参数可以写多个
public class SpringConfig { }
//JDBC配置类
//@Configuration 可以写也可以不写
public class JdbcConfig {
@Bean(name="dataSource")
public DataSource createDataSource() {
try {
ComboPooledDataSource ds = new ComboPooledDataSource();
ds.setUser("root");
ds.setPassword("root");
ds.setDriverClass("com.mysql.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql://localhost:3306/spring");
return ds;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Bean(name = "queryRunner")
@Scope("prototype")
public QueryRunner createQueryRunner(DataSource dataSource) {
return new QueryRunner(dataSource);
}
}
当我们使用了@Import注解后,有@Import注解的类就是主配置类,导入的都是子配置类。
如有几个配置类,关于JDBC的,关于事务的,都可以使用@Import导入
//使用时,只需要传入主配置类就可以了
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
如果不使用@Import注解,使用其他方式也可以达到同样的效果,比如:
第一种:可以将子配置类作为参数传递过去
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class,
JdbcConfig.class);
第二种:子配置类中加入Configuration注解,并在主配置类的扫描包里面加入子配置类所在的包
@Configuration
//所在包为 com.config
public class JdbcConfig { }
@Configuration
@ComponentScan(basePackages = "com.mg","com.config")
public class SpringConfig { }
使用时:
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class)
@PropertySource
作用:用于加载.properties 文件中的配置。例如我们配置数据源时,可以把连接数据库的信息写到properties 配置文件中,就可以使用此注解指定 properties 配置文件的位置。 属性: value[]:用于指定 properties 文件位置。如果是在类路径下,需要写上 classpath:
//如之前用@Bean创建DataSource时,数据库信息写死,则可以修改为:
1. 创建jdbcConfig.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring
jdbc.username=root
jdbc.password=root
2.类中修改
//引入properties文件,写配置文件的具体位置,如果是在类路径下,需要写上 classpath:
@PropertySource("classpath:jdbcConfig.properties")
public class JdbcConfig {
//获取properties文件的值
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean(name="dataSource")
public DataSource createDataSource() {
try {
ComboPooledDataSource ds = new ComboPooledDataSource();
//设置值
ds.setUser(username);
ds.setPassword(password);
ds.setDriverClass(driver);
ds.setJdbcUrl(url);
return ds;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Bean(name = "queryRunner")
@Scope("prototype")
public QueryRunner createQueryRunner(DataSource dataSource) {
return new QueryRunner(dataSource);
}
}
//注意:@PropertySource("classpath:jdbcConfig.properties")这个注解也可以加到主配置类上
//主配置类
@Configuration
@ComponentScan(basePackages = "com.mg")
@Import(JdbcConfig.class)
@PropertySource("classpath:jdbcConfig.properties")
public class SpringConfig { }
//子配置类
public class JdbcConfig {
//获取properties文件的值
@Value("${jdbc.driver}")
………………………………………………………………
}
@Qualifier
另一种用法,使用在参数上,可单独使用。如有多个对象时,需要使用该注解指定用哪个,使用注解时如果方法有参数,Spring回去容器中查找是否有可用对象,查找方式和AutoWired一致,即:按照类型找到唯一一个则注入成功,找到多个则把参数名作为bean的id去找,找到也可以注入成功,如果还不能唯一确定则报错
@Bean(name = "queryRunner")
@Scope("prototype")
public QueryRunner createQueryRunner(@Qualifier("ds2") DataSource dataSource) {
return new QueryRunner(dataSource);
}
@Bean(name="ds1")
public DataSource ds1() { }
@Bean(name="ds2")
public DataSource ds2() { }
spring的IOC实现账户的CRUD(纯注解实现)
引入依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>commons-dbutils</groupId>
<artifactId>commons-dbutils</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
</dependency>
</dependencies>
建表
create table account (
id int primary key auto_increment,
name varchar (40),
money float
)character set utf8 collate utf8_general_ci;
insert into account(name, money) values('aaa', 1000);
insert into account (name,money) values ('bbb',1000);
insert into account (name, money) values('ccc', 1000) ;
实体类
public class Account implements Serializable {
private Integer id;
private String name;
private Float money;
//生成set/get
}
Service接口及实现类
public interface IAccountService {
List<Account> findAllAccount();
}
@Service("accountService")
public class AccountServiceImpl implements IAccountService {
@Autowired
private IAccountDao accountDao;
public List<Account> findAllAccount() {
return accountDao.findAllAccount();
}
}
Dao接口及实现类
public interface IAccountDao {
List<Account> findAllAccount();
}
@Repository("accountDao")
public class AccountDaoImpl implements IAccountDao {
@Autowired
private QueryRunner queryRunner;
public List<Account> findAllAccount() {
try {
return queryRunner.query("select * from account",
new BeanListHandler<Account>(Account.class)
);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
数据库相关配置文件 jdbcConfig.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring
jdbc.username=root
jdbc.password=root
Spring配置类
JDBC相关配置类,子配置类
//@Configuration 可以写也可以不写
@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;
@Bean(name="dataSource")
public DataSource createDataSource() {
try {
ComboPooledDataSource ds = new ComboPooledDataSource();
ds.setUser(username);
ds.setPassword(password);
ds.setDriverClass(driver);
ds.setJdbcUrl(url);
return ds;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Bean(name = "queryRunner")
@Scope("prototype")
public QueryRunner createQueryRunner(DataSource dataSource) {
return new QueryRunner(dataSource);
}
}
Spring主配置类
@Configuration
@ComponentScan(basePackages = "com.mg")
@Import(JdbcConfig.class)
public class SpringConfig { }
测试使用
@Test
public void test2() {
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
IAccountService accountService = ac.getBean("accountService", IAccountService.class);
List<Account> accounts = accountService.findAllAccount();
for(Account account:accounts) {
System.out.println(account);
}
}