数据库crud操作 xml版
1.持久层
public class AccountDaoImpl implements AccountDao {
private QueryRunner runner;
public void setRunner(QueryRunner runner) {
this.runner = runner;
}}
2.业务层
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}}
3.测试类
@Test
public void testFindAll() {
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
AccountService as = ac.getBean("AccountServiceImpl",AccountService.class);
//3.执行方法
List<Account> accounts = as.findAllAccount();
for(Account account : accounts){
System.out.println(account);
}}
4.bean 配置
<context:component-scan base-package="com.wyc" ></context:component-scan>
<!--把对象的创建交给spring来管理-->
<bean id="AccountServiceImpl" class="com.wyc.Service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"></property>
</bean>
<bean id="accountDao" class="com.wyc.dao.impl.AccountDaoImpl">
<property name="runner" ref="runner"></property>
</bean>
<bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
<!--注入数据源-->
<constructor-arg name="ds" ref="dataSource"></constructor-arg>
</bean>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.cj.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
<property name="user" value="root"></property>
<property name="password" value="123"></property>
</bean>
注解版
注解无法配置 不是我们自己写的类时 列如 runner 无法去源码中加注解 所以需要一个配置类 来代替context的功能和其他注解
Configuration
作用:指定当前类是一个配置类
细节:当配置类作为 AnnotationConfigApplicationContext 对象创建的参数时,该注解可以不写。
ComponentScan
作用:用于通过注解指定spring在创建容器时要扫描的包
属性: value:它和basePackages的作用是一样的,都是用于指定创建容器时要扫描的包。
我们使用此注解就等同于在xml中配置了: <context:component-scan base-package="com.itheima"></context:component-scan>
@Configuration //指定当前类为一个配置类
@ComponentScan("com.wyc") //value也可以 指定
public class SpringConfiguration {
@Bean(name = "runner")
@Scope("prototype")
public QueryRunner createQueryRunner(DataSource dataSource){
return new QueryRunner(dataSource);
}
@Bean(name = "dataSource")
public DataSource createDataSource(){
ComboPooledDataSource ds= new ComboPooledDataSource():
try {
ds.setDriverClass("com.mysql.cj.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql://localhost:3306/test");
ds.setUser("root");
ds.setPassword("123");
return ds;
} catch (Exception e) {
e.printStackTrace();
}}}
用这一段来代替 runner 一下的xml配置
@Bean 作用:用于把当前方法的返回值作为bean对象存入spring的ioc容器中
属性: name:用于指定bean的id。当不写时,默认值是当前方法的名称
细节:当我们使用注解配置方法时,如果方法有参数,spring框架会去容器中查找有没有可用的bean对象。
查找的方式和Autowired注解的作用是一样的,先找数据类型唯一,如果有多个,在看名字
@scope () 单列或多列
//ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class); 通过注解配置的
AccountService as = ac.getBean("accountService",AccountService.class);
List<Account> accounts = as.findAllAccount();
for(Account account : accounts){
System.out.println(account);
}}
抽取jdbc 到一个单独的类
@Configuration //指定当前类为一个配置类
@ComponentScan(value = {"com.wyc","config"}) //value也可以 指定
public class SpringConfiguration {
}
@Configuration 说明为一个配置类
public class JdbcConfig {
@Bean(name = "runner")
@Scope("prototype")
public QueryRunner createQueryRunner(DataSource dataSource){
return new QueryRunner(dataSource);
}
@Bean(name = "dataSource")
public DataSource createDataSource(){
ComboPooledDataSource ds= new ComboPooledDataSource();
try {
ds.setDriverClass("com.mysql.cj.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql://localhost:3306/test");
ds.setUser("root");
ds.setPassword("123");
return ds;
} catch (Exception e) {
throw new RuntimeException(e);}}}
没有传入AnnotationConfigApplicationContext 所以必须写为一个配置类,主配置类中需要添加 config 才能扫描到 JdbcConfig类
或者在AnnotationConfigApplicationContext( SpringConfiguration.class,JdbcConfig.class ) 加入也可以不用说明为配置类
需要扫描的包 也可以不用写了 ,会根据传入的自动去扫描, ,但是体现不出配置文件的层级关系了
import
导入 其他的子类的 配置文件字节码 ,与前面的作用一样,更好用
value:用于指定其他配置类的字节码。可以有多个,是一个数组
当我们使用Import的注解之后,有Import注解的类就父配置类,而导入的都是子配置类
@ComponentScan(value = {"com.wyc"}) //value也可以 指定
@Import(JdbcConfig.class)
public class SpringConfiguration {}
public class JdbcConfig {]
public void testFindAll() {
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
AccountService as = ac.getBean("accountService",AccountService.class);
//3.执行方法
List<Account> accounts = as.findAllAccount();
for(Account account : accounts){
System.out.println(account);
}}
PropertySource
作用:用于指定properties文件的位置
属性: value:指定文件的名称和路径。 关键字:classpath,表示类路径下
@ComponentScan("com.wyc") //value也可以 指定
@Import(JdbcConfig.class)
@PropertySource("classpath:jdbc.properties") classpath表示类路径下 有包还可以写classpath:com/wyc...
public class SpringConfiguration {}
public class JdbcConfig {
@Value("${driver}")
private String driver;
@Value("${url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}") 大坑配置文件写法 不然会输出电脑的 username
private String password;
@Bean(name = "dataSource")
public DataSource createDataSource(){
ComboPooledDataSource ds= new ComboPooledDataSource();
try {
ds.setDriverClass(driver);
ds.setJdbcUrl(url);
ds.setUser(username);
ds.setPassword(password);
return ds;
} catch (Exception e) {
throw new RuntimeException(e);
@Qualifier
@Override 默认先找 数据类型 @Qualifier 根据名称找
public QueryRunner createQueryRunner(@Qualifier("ds1") DataSource dataSource){
return new QueryRunner(dataSource);
}
@Bean(name = "ds1")
public DataSource createDataSource(){}
@Bean(name = "ds2")
public DataSource createDataSource1(){}
整合Junit
Spring整合junit的配置
1、导入spring整合junit的jar(坐标)
2、使用Junit提供的一个注解把原有的main方法替换了,替换成spring提供的 @Runwith 用来创建容器
3、告知spring的运行器,spring和ioc创建是基于xml还是注解的,并且说明位置
@ContextConfiguration
locations:指定xml文件的位置,加上classpath关键字,表示在类路径下 "locations: classpath:bean.xml"
classes: 指定注解类所在地位置
当我们使用spring 5.x版本的时候,要求junit的jar必须是4.12及以上
@RunWith(SpringJUnit4ClassRunner.class) 固定的
@ContextConfiguration(classes = SpringConfiguration.class)
public class AccountServiceTest {
@Autowired
private AccountService as;
@Test
public void testFindAll() {
List<Account> accounts = as.findAllAccount();
for(Account account : accounts){
System.out.println(account);
}
}