spring02

Spring框架

今日内容

  • 能够编写spring的IOC的注解代码
  • 能够编写spring使用注解实现组件扫描
  • 能够说出spring的IOC的相关注解的含义
  • 能够实现spring框架整合JUnit

DBCP连接池的使用

由Apache开发,通过数据库连接池,可以让程序自动管理数据库连接的释放和断开。DataSource接口实现类BasicDataSource。

//创建DataSource接口实现类对象
BasicDataSource dataSource = new BasicDataSource();
//设置数据库驱动类
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
//设置连接URL
dataSource.setUrl("jdbc:mysql://localhost:3306/test");
//设置连接用户名和密码
dataSource.setUsername("root");
dataSource.setPassword("root");

DBUtils实现账户表增删改查

private QueryRunner qr ;

@Before
public void before(){
    BasicDataSource dataSource = new BasicDataSource();
    //设置数据库驱动类
    dataSource.setDriverClassName("com.mysql.jdbc.Driver");
    //设置连接URL
    dataSource.setUrl("jdbc:mysql://localhost:3306/test");
    //设置连接用户名和密码
    dataSource.setUsername("root");
    dataSource.setPassword("root");
    qr = new QueryRunner(dataSource);
}

/**
 * DBUtils查询全部
 */
@Test
public void testQueryByList()throws SQLException{
    String sql = "select * from account";
    List<Account> list = qr.query(sql, new BeanListHandler<Account>(Account.class));
    if(list != null &&  list.size() > 0 ){
        for(Account account : list){
            System.out.println(account);
        }
    }
}

/**
 * DBUtils主键查询
 */
@Test
public void testQueryById() throws SQLException {
    String sql = "select * from account where id = ?";
    Account account = qr.query(sql, new BeanHandler<Account>(Account.class), 3);
    System.out.println(account);
}

/**
 * DBUtils删除数据
 */
@Test
public void testDelete()throws SQLException{
    String sql = "delete from account where id = ?";
    int row = qr.update(sql, 4);
    System.out.println("影响行数:"+row);
}

/**
 * DBUtils更新数据
 */
@Test
public void testUpdate()throws  SQLException{
    String sql = "update account set name = ? , money = ? where id = ?";
    int row = qr.update(sql, "赵六哥哥",100.33,4);
    System.out.println("影响行数:"+row);
}

/**
 * DBUtils新增数据
 */
@Test
public void testInsert() throws SQLException {
   String sql = "insert into account(name,money) values (?,?)";
   int row = qr.update(sql,"赵六",99);
   System.out.println("操作影响行数:"+row);
}

Account表的CRUD(SpringIOC实现)

实现思想

  • maven工程引入坐标

    • junit
    • mysql驱动
    • dbcp数据库连接池
    • dbutils数据库工具
    • dao层service层涉及到很多对象的管理(Spring-context)
  • 开发步骤分析

    • 引入坐标(如上)
    • Account表的pojo开发
    • 开发dao层代码(dao接口和实现类)
    • 在dao实现类当中使用dbutils操作数据库
    • sevice层开发
    • 上述过程中涉及到的对象和对象之间的引用注入交给Spring管理
  • applicationContext.xml配置

    <!-- 配置dbcp连接池-->
    <bean id="basicDataSource" class="org.apache.commons.dbcp2.BasicDataSource">
        <!-- BasicDataSource成员注入-->
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/test"></property>
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>
    </bean>
    
    <!-- 配置QueryRunner-->
    <bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner">
        <!-- 构造方法注入-->
        <constructor-arg name="ds" ref="basicDataSource"></constructor-arg>
    </bean>
    
    <!-- 配置业务层-->
    <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
        <!-- 业务层set方法,注入-->
        <property name="accountDao" ref="accountDao"></property>
    </bean>
    
    <!-- 配置持久层-->
    <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl">
        <!-- 持久层queryRunner注入-->
        <property name="qr" ref="queryRunner"></property>
    </bean>
    
  • AccountDaoImpl

    private QueryRunner qr;
    
    public void setQr(QueryRunner qr) {
        this.qr = qr;
    }
    
    @Override
    public void saveAccount(Account account) throws SQLException {
        String sql = "insert into account values(?,?,?)";
        qr.update(sql,null,account.getName(),account.getMoney());
    }
    
  • AccountServiceImpl

    private AccountDao accountDao;
    
    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }
    
    @Override
    public void saveAccount(Account account) {
        try {
            accountDao.saveAccount(account);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    
  • 测试程序

    @Test
    public void testSaveAccount(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        AccountService service = applicationContext.getBean("accountService", AccountService.class);
        Account account = new Account();
        account.setName("小名");
        account.setMoney(200.32);
        service.saveAccount(account);
    }
    

Spring注解开发

bean标签和注解的对应

  • 添加applicationContext配置文件命名空间
<?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"
>
    
    <!-- 开启spring的注解扫描,扫描包中类的注解-->
    <context:component-scan base-package="com.itheima"></context:component-scan>
</beans>
  • bean标签对应注解@Component

    • 注解属性value:bean标签的id属性
    • 不指定value属性,默认就是类名,首字母小写
    • 该注解衍生出了三个注解,@Controller,@Service,@Repository,用法和@Componet一致,为了更加清晰的提现层的概念。
  • bean标签属性scope对应注解@Scope

    • 注解属性value:singleton,prototype
  • bean标签属性init-method对应注解@PostConstruct

  • bean标签属性destroy-method对应注解@PreDestroy

  • service层

    @Component("accountService")
    @Service("accountService")
    @Scope("prototype")
    public class AccountServiceImpl implements AccountService {
    
        private AccountDao accountDao;
    
        public void setAccountDao(AccountDao accountDao) {
            this.accountDao = accountDao;
        }
    
        @Override
        public void saveAccount(Account account) {
            accountDao.saveAccount(account);
        }
    }
    
  • dao层

    //@Component("accountDao")
    public class AccountDaoImpl implements AccountDao {
    
        @Override
        public void saveAccount(Account account) {
            System.out.println("模拟转账");
        }
    }
    
  • 测试注解

    @Test
    public  void testIOC(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        AccountService accountService = context.getBean("accountService", AccountService.class);
        AccountDao accountDao = context.getBean("accountDao",AccountDao.class);
        System.out.println(accountService);
        System.out.println(accountDao);
        context.close();
    }
    

依赖注入注解

  • @Autowired注解(Spring框架提供)

    按照类型注入,如果无法确定唯一类型(接口有多个实现类),需要配合疏解@Qualifier的使用,@Qualifier(“id”)。

    注解注入,不要setXXX方法。

  • 业务层

    @Service("accountService")
    @Scope("singleton")
    public class AccountServiceImpl implements AccountService {
    
        @Autowired
        @Qualifier("accountDao")
        private AccountDao accountDao;
    
    
        @Override
        public void saveAccount(Account account) {
            accountDao.saveAccount(account);
        }
    }
    
  • @Resource注解(JDK提供)

    • 注解属性name:配置类的id
    @Resource(name="accountDao")
    private AccountDao accountDao;
    

半注解半xml改造(CRUD)

企业开发的主流

注意:往往第三方jar中的对象我们使用xml配置(比如dbcp数据库连接池、dbutils的QueryRunner),类似于service层和dao层的实现类,这属于我们自己写的代码,往往会使用注解,这就是半xml半注解的模式。

  • applicationContext.xml配置

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           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
    ">
        <!-- 开启Spring的注解扫描-->
        <context:component-scan base-package="com.itheima"></context:component-scan>
        <!-- 配置dbcp连接池-->
        <bean id="basicDataSource" class="org.apache.commons.dbcp2.BasicDataSource">
            <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
            <property name="url" value="jdbc:mysql://localhost:3306/test"></property>
            <property name="username" value="root"></property>
            <property name="password" value="root"></property>
        </bean>
        <!-- 配置QueryRunner对象-->
        <bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner">
            <constructor-arg ref="basicDataSource"></constructor-arg>
        </bean>
    </beans>
    
  • dao层

    @Repository("accountDao")
    public class AccountDaoImpl implements AccountDao {
        @Autowired
        @Qualifier("queryRunner")
        private QueryRunner qr;
    
        @Override
        public void saveAccount(Account account) throws SQLException {
            String sql = "insert into account values(?,?,?)";
            qr.update(sql,null,account.getName(),account.getMoney());
        }
    }
    
  • service层

    @Service("accountService")
    public class AccountServiceImpl implements AccountService {
        @Autowired
        @Qualifier("accountDao")
        private AccountDao accountDao;
    
        @Override
        public void saveAccount(Account account) {
            try {
                accountDao.saveAccount(account);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    
  • 测试

    @Test
    public void testSaveAccount(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        AccountService service = context.getBean("accountService", AccountService.class);
        Account account = new Account();
        account.setName("testName");
        account.setMoney(0.99);
        service.saveAccount(account);
    }
    

纯注解开发(CRUD)

  • @Configuration标识当前类是Spring的一个配置类

  • @ComponentScan替代xml中的<context:component-scan/>

  • @Import引入其他配置类,被引入的配置类可以不加@Configuration注解

  • @PropertySource:引入外部properties文件,注意加classpath:

  • @Value对成员变量赋值

  • @Bean将一个方法的返回值对象加入到Spring的容器当中管理

  • @Qualifier可以使用在方法上,表明对应的形参引入/注入的对象类型

  • SpringConfig框架启动配置类

    //Spring配置类,框架启动入口
    @Configuration
    //启动注解扫描
    @ComponentScan({"com.itheima"})
    public class SpringConfig {
    
        //方法的返回值,加入到SpringIOC容器中管理
        @Bean("basicDataSource")
        public DataSource createDataSource(){
            BasicDataSource basicDataSource = new BasicDataSource();
            basicDataSource.setDriverClassName("com.mysql.jdbc.Driver");
            basicDataSource.setUrl("jdbc:mysql://localhost:3306/test");
            basicDataSource.setUsername("root");
            basicDataSource.setPassword("root");
            return basicDataSource;
        }
        //方法的返回值,加入到SpringIOC容器中管理
        @Bean("queryRunner")
        //@Qualifier("basicDataSource"),对参数进行注入
        public QueryRunner createQueryRunner( @Qualifier("basicDataSource") DataSource ds){
            QueryRunner queryRunner = new QueryRunner(ds);
            return  queryRunner;
        }
    }
    
  • dao层

    @Repository("accountDao")
    public class AccountDaoImpl implements AccountDao {
        @Autowired
        @Qualifier("queryRunner")
        private QueryRunner qr;
    
        @Override
        public void saveAccount(Account account) throws SQLException {
            String sql = "insert into account values(?,?,?)";
            qr.update(sql,null,account.getName(),account.getMoney());
        }
    }
    
  • service层

    @Service("accountService")
    public class AccountServiceImpl implements AccountService {
        @Autowired
        @Qualifier("accountDao")
        private AccountDao accountDao;
    
        @Override
        public void saveAccount(Account account) {
            try {
                accountDao.saveAccount(account);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    
  • 测试

    @Test
    public void testAnnotation() {
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        AccountService service = context.getBean("accountService", AccountService.class);
        Account account = new Account();
        account.setName("testAnnoName");
        account.setMoney(1.98);
        service.saveAccount(account);
    
    }
    

注解开发的SpringConfig配置优化

  • SpringConfig框架启动配置类

    //Spring配置类,框架启动入口
    @Configuration
    //启动注解扫描
    @ComponentScan({"com.itheima"})
    //引入JDBC的配置类
    @Import({JDBCConfig.class})
    public class SpringConfig {
    }
    
  • JDBCConfig配置类

    @Configuration
    @PropertySource("classpath:jdbc.properties")
    public class JDBCConfig {
    
        //注入配置文件中的键值对
        @Value("${jdbc.driver}")
        private String driverClassName;
    
        @Value("${jdbc.url}")
        private String url;
    
        @Value("${jdbc.username}")
        private String username;
    
        @Value("${jdbc.password}")
        private String password;
    
        //方法的返回值,加入到SpringIOC容器中管理
        @Bean("basicDataSource")
        public DataSource createDataSource(){
            BasicDataSource basicDataSource = new BasicDataSource();
            basicDataSource.setDriverClassName(driverClassName);
            basicDataSource.setUrl(url);
            basicDataSource.setUsername(username);
            basicDataSource.setPassword(password);
            return basicDataSource;
        }
        //方法的返回值,加入到SpringIOC容器中管理
        @Bean("queryRunner")
        //@Qualifier("basicDataSource"),对参数进行注入
        public QueryRunner createQueryRunner(@Qualifier("basicDataSource") DataSource ds){
            QueryRunner queryRunner = new QueryRunner(ds);
            return  queryRunner;
        }
    }
    

Spring对Junit的支持

  • junit运行的时候底层使用了Runner对象,有一个默认使用的Runner对象。
  • Spring对junit的支持,其实是自己实现了一个Runner对象(按照junit runner的要求实现)
  • Spring对junit的支持的体现
    • 好处一:配置完之后,不需要我们手动的启动Spring,而是会很方便的启动Spring
    • 好处二:可以在junit测试类中使用@AutoWired等方式注入对象,直接对其进行调用测试
  • 使用步骤
    • 引入jar
    • 配置你的测试类
//Spring框架中的Runner对象,替换Junit中的runner对象
@RunWith(SpringJUnit4ClassRunner.class)

//框架启动入口,配置类启动
@ContextConfiguration(classes = SpringConfig.class)

//框架启动入口,xml配置文件启动
//@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class MainTest 
{
	//注入业务层接口
    @Autowired
    @Qualifier("accountService")
    private AccountService service;


    @Test
    public void testAnnotation() {

        Account account = new Account();
        account.setName("testAnnoName3");
        account.setMoney(3.98);
        service.saveAccount(account);

    }
}

猜你喜欢

转载自blog.csdn.net/qq_35670694/article/details/89136348