程序员社区

Spring基于注解开发案例

文章目录

      • 环境搭建
        • 0.实体类
        • 1.业务层接口
        • 2.业务层实现类
        • 3.持久层接口
        • 4.持久层实现类
        • 5.配置文件:bean.xml
        • 6.测试类
      • 通过注解代替bean.xml配置文件
        • @Component("account")
        • @Value("zhangsan")
        • @Service("accountDao")
        • @Autowired
        • @Repository("accountDao")
        • @Configuration
        • @ComponentScan
        • @Bean
        • 测试
        • @Import
        • @PropertySource
        • Spring整合Junit
      • 总结
        • 0.实体类
        • 1.业务层接口
        • 2.业务层实现类
        • 3.持久层接口
        • 4.持久层实现类
        • 5.SpringConfig配置主类
        • 6.jdbcConfig.properties
        • 7.JDBCConfig配置副类
        • 8.测试类

环境搭建

数据库:

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);

在这里插入图片描述
项目的目录结构:
在这里插入图片描述
pom.xml:

<dependencies>
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.18</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.0.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/junit/junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/c3p0/c3p0 -->
        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/commons-dbutils/commons-dbutils -->
        <dependency>
            <groupId>commons-dbutils</groupId>
            <artifactId>commons-dbutils</artifactId>
            <version>1.7</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/junit/junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

0.实体类

public class Account {
    private Integer id;
    private String name;
    private Float money;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Float getMoney() {
        return money;
    }

    public void setMoney(Float money) {
        this.money = money;
    }

    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", money=" + money +
                '}';
    }
}

1.业务层接口

public interface AccountService {
    //查询所有
    List<Account> findAllAccount();
    //查询一个
    Account findAccountById(Integer id);
    //保存
    void saveAccount(Account account);
    //更新
    void updateAccount(Account account);
    //删除
    void deleteAccount(Integer id);
}

2.业务层实现类

//业务层实现类,业务层调用持久层
public class AccountServiceImpl implements AccountService{
    private AccountDao accountDao;

    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    public List<Account> findAllAccount() {
        return accountDao.findAllAccount();
    }

    public Account findAccountById(Integer id) {
        return accountDao.findAccountById(id);
    }

    public void saveAccount(Account account) {
        accountDao.saveAccount(account);
    }

    public void updateAccount(Account account) {
        accountDao.updateAccount(account);
    }

    public void deleteAccount(Integer id) {
        accountDao.deleteAccount(id);
    }
}

3.持久层接口

//账户的持久层接口
public interface AccountDao {
    //查询所有
    List<Account> findAllAccount();
    //查询一个
    Account findAccountById(Integer id);
    //保存
    void saveAccount(Account account);
    //更新
    void updateAccount(Account account);
    //删除
    void deleteAccount(Integer id);
}

4.持久层实现类

//持久层实现类
public class AccountDaoImpl implements AccountDao {
    private QueryRunner runner;

    public void setRunner(QueryRunner runner) {
        this.runner = runner;
    }

    public List<Account> findAllAccount() {
        try {
            return runner.query("select * from account",new BeanListHandler<Account>(Account.class));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public Account findAccountById(Integer id) {
        try {
            return runner.query("select * from account where id=?",new BeanHandler<Account>(Account.class),id);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void saveAccount(Account account) {
        try {
            runner.update("insert into account(name,money) values(?,?)",account.getName(),account.getMoney());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void updateAccount(Account account) {
        try {
            runner.update("update account set name=?,money=? where id=?",account.getName(),account.getMoney(),account.getId());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void deleteAccount(Integer id) {
        try {
            runner.update("delete from account where id=?",id);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

5.配置文件: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
        http://www.springframework.org/schema/beans/spring-beans.xsd">
        
	<!--Spring在创建容器时,要扫描的包-->
    <context:component-scan base-package="com.hh"/>
	
	<!--配置实体类-->
	<bean id="account" class="com.hh.domain.Account">
        <property name="name" value="zhangsan"/>
        <property name="money" value="2000"/>
    </bean>
    
    <!--配置AccountService-->
    <bean id="accountService" class="com.hh.service.AccountServiceImpl">
        <!--注入accountDao-->
        <property name="accountDao" ref="accountDao"/>
    </bean>

    <!--配置AccountDao-->
    <bean id="accountDao" class="com.hh.dao.AccountDaoImpl">
        <!--注入QueryRunner-->
        <property name="runner" ref="queryRunner"/>
    </bean>

    <!--配置QueryRunner-->
    <bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
        <!--注入数据源-->
        <constructor-arg name="ds" ref="dataSource"/>
    </bean>

    <!--配置数据源-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!--连接数据库的必备信息-->
        <property name="driverClass" value="com.mysql.jdbc.Driver"/>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring"/>
        <property name="user" value="root"/>
        <property name="password" value="123"/>
    </bean>
</beans>

6.测试类

public class MyTest {
    @Test
    public void testFindAll(){
        //获取Spring核心容器
        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        //得到业务层对象
        AccountService service =
                context.getBean("accountService", AccountService.class);
       List<Account> accounts =  service.findAllAccount();
       for(Account account :accounts){
           System.out.println(account);
       }
    }

    @Test
    public void testFindone(){
        //获取Spring核心容器
        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        //得到业务层对象
        AccountService service =
                context.getBean("accountService", AccountService.class);
        Account account = service.findAccountById(3);
        System.out.println(account);
    }

    @Test
    public void testSave(){
        //获取Spring核心容器
        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        //得到业务层对象
        AccountService service =
                context.getBean("accountService", AccountService.class);
        //获取Account对象
        Account account = context.getBean("account",Account.class);
        service.saveAccount(account);
    }

    @Test
    public void testUpdate(){
        //获取Spring核心容器
        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        //得到业务层对象
        AccountService service =
                context.getBean("accountService", AccountService.class);
        context.getBean("account");
        //获取Account对象
        Account account = service.findAccountById(4);
        account.setMoney(3000f);
        service.updateAccount(account);
    }

    @Test
    public void testDelete(){
        //获取Spring核心容器
        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        //得到业务层对象
        AccountService service =
                context.getBean("accountService", AccountService.class);
        context.getBean("account");
        service.deleteAccount(4);
    }
}

通过注解代替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
        http://www.springframework.org/schema/beans/spring-beans.xsd">
        
	<!--Spring在创建容器时,要扫描的包-->
    <context:component-scan base-package="com.hh"/>
	
	<!--配置实体类-->
	<bean id="account" class="com.hh.domain.Account">
        <property name="name" value="zhangsan"/>
        <property name="money" value="2000"/>
    </bean>
    
    <!--配置AccountService-->
    <bean id="accountService" class="com.hh.service.AccountServiceImpl">
        <!--注入accountDao-->
        <property name="accountDao" ref="accountDao"/>
    </bean>

    <!--配置AccountDao-->
    <bean id="accountDao" class="com.hh.dao.AccountDaoImpl">
        <!--注入QueryRunner-->
        <property name="runner" ref="queryRunner"/>
    </bean>

    <!--配置QueryRunner-->
    <bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
        <!--注入数据源-->
        <constructor-arg name="ds" ref="dataSource"/>
    </bean>

    <!--配置数据源-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!--连接数据库的必备信息-->
        <property name="driverClass" value="com.mysql.jdbc.Driver"/>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring"/>
        <property name="user" value="root"/>
        <property name="password" value="123"/>
    </bean>
</beans>

既然是使用注解开发,那么思考一个问题,要通过哪些注解把上面的xml文件去掉,不再使用bean.xml呢?

@Component(“account”)

使用@Component来创建Account对象,将Account对象放进IOC容器
在这里插入图片描述
代替bean.xml中下面的配置:

<bean id="account" class="com.hh.domain.Account">
</bean>

@Value(“zhangsan”)

如果不想在测试类中调用setter方法初始化,可以使用注解依赖注入
在这里插入图片描述
代替bean.xml中下面的配置:

<bean id="account" class="com.hh.domain.Account">
        <property name="name" value="zhangsan"/>
        <property name="money" value="2000"/>
</bean>

@Service(“accountDao”)

使用@Service来创建accountService对象
在这里插入图片描述
代替bean.xml中下面的配置:

<!--配置AccountService-->
<bean id="accountService" class="com.hh.service.AccountServiceImpl">
    <!--注入accountDao-->
    <property name="accountDao" ref="accountDao"/>
</bean>

@Autowired

由于AccountServiceImpl中有一个bean对象属性,因此可以通过@Autowired依赖注入,可以省略setter方法
在这里插入图片描述

@Repository(“accountDao”)

使用@Repository来创建accountDao对象
在这里插入图片描述
代替bean.xml中下面的配置:

<!--配置AccountDao-->
    <bean id="accountDao" class="com.hh.dao.AccountDaoImpl">
        <!--注入QueryRunner-->
        <property name="runner" ref="queryRunner"/>
    </bean>

@Configuration

作用:指定当前类是一个配置类,作用和bean.xml相同

//该类是一个配置类,作用和bean.xml相同
@Configuration
public class SpringConfig {

}

@ComponentScan

作用:用于通过注解指定Spring在创建容器中要扫描的包
属性:value和bacePackages作用相同,都是指定要扫描的包
作用等同于xml中的:<context:component-scan base-package="com.hh"/>
在这里插入图片描述

使用@ComponentScan指定要扫描的包
在这里插入图片描述
代替bean.xml中下面的配置:

 <!--Spring在创建容器时,要扫描的包-->
<context:component-scan base-package="com.hh"/>

@Bean

作用:用于把当前方法的返回值作为bean对象存入Spring容器中
属性:name:用于指定bean的id,不写时默认为当前方法的名称
细节:当我们使用注解配置方法时,如果方法有参数,Spring框架回去容器中找有没有可用的bean对象,查找的方式和Autowired一样。
在这里插入图片描述
在这里插入图片描述
代替bean.xml中下面的配置:

<!--配置QueryRunner-->
<bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
     <!--注入数据源-->
     <constructor-arg name="ds" ref="dataSource"/>
 </bean>

 <!--配置数据源-->
 <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
     <!--连接数据库的必备信息-->
     <property name="driverClass" value="com.mysql.jdbc.Driver"/>
     <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring"/>
     <property name="user" value="root"/>
     <property name="password" value="123"/>
 </bean>

 <bean id="account" class="com.hh.domain.Account">
     <property name="name" value="zhangsan"/>
     <property name="money" value="2000"/>
 </bean>

到目前为止,我们已经把配置文件中所有的配置都去掉了,目前就是下面这个样子,同时就可以吧这个bean.xml删除了:
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
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
</beans>

测试

下面我们需要对注解改造过的项目进行测试,那么问题来了,之前我们都是通过配置文件bean.xml来获取Spring的IOC核心容器ApplicationContext,现在注解删了,还怎么获取?
下面要通过ApplicationContext的另一个实现类:
在这里插入图片描述

public class MyTest {
   	@Test
    public void testSave(){
        //获取Spring核心容器
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        //得到业务层对象
        AccountService service =
                context.getBean("accountService", AccountService.class);
        //获取Account对象
        Account account = context.getBean("account",Account.class);
        service.saveAccount(account);
    }

在这里插入图片描述

@Import

当配置类作为容器对象AnnotationConfigApplicationContext的参数时,@Configuration注解可以省略不写

在这里插入图片描述
配置类JDBCConfig:

//和Spring连接数据库相关的配置类
public class JDBCConfig {
    //用于创建一个QueryRunner对象
    @Bean(name="queryRunner")
    public QueryRunner createQueryRunner(DataSource dataSource){
        return new QueryRunner(dataSource);
    }
    //创建一个DataSource对象
    @Bean(name="dataSource")
    public DataSource createDataSource() throws PropertyVetoException {
        ComboPooledDataSource ds =  new ComboPooledDataSource();
        ds.setDriverClass("com.mysql.jdbc.Driver");
        ds.setJdbcUrl("jdbc:mysql://localhost:3306/spring");
        ds.setUser("root");
        ds.setPassword("123");
        return ds;
    }
}

如上图,重新在config包下面写一个配置类JDBCConfig,如果把这个配置类的注解@Configuration省略不写,就要把这个配置类JDBCConfig.class加到容器对象的参数中
在这里插入图片描述
在这里插入图片描述
如果在JDBCConfig类上加了@Configuration注解,那么就不需要再容器对象参数中写入JDBCConfig.class
在这里插入图片描述
在这里插入图片描述
问题来了,现在有两个配置类SpringConfig和JDBCConfig,如果我既不想在JDBCConfig类上加一个@Configuration注解,也不想在容器对象参数中加入JDBCConfig.class呢?这个时候就需要引入一个新注解@Import。把配置类JDBCConfig导入配置类SpringConfig中。

@Import作用:用于导入其他的配置类
使用Import注解后,有Import注解的类就是主配置类,导入的都是副配置类
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

@PropertySource

现在还有一个问题注意看SpringConfig配置类:

//和Spring连接数据库相关的配置类
public class JDBCConfig {
    //用于创建一个QueryRunner对象
    @Bean(name="queryRunner")
    public QueryRunner createQueryRunner(DataSource dataSource){
        return new QueryRunner(dataSource);
    }
    //创建一个DataSource对象
    @Bean(name="dataSource")
    public DataSource createDataSource() throws PropertyVetoException {
        ComboPooledDataSource ds =  new ComboPooledDataSource();
        ds.setDriverClass("com.mysql.jdbc.Driver");
        ds.setJdbcUrl("jdbc:mysql://localhost:3306/spring");
        ds.setUser("root");
        ds.setPassword("123");
        return ds;
    }
}

在这里插入图片描述
写一个jdbcConfig.properties配置文件:

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/spring
username=root
password=123

在配置类JDBCConfig中写入这几个属性,并指定值:
在这里插入图片描述
在这里插入图片描述
@PropertySource
作用:用于指定properties文件的位置
属性:value用于指定文件的名称和路径
关键字:classPath:表示类路径下
在这里插入图片描述

Spring整合Junit

1.导入spring整合Junit的jar包

<!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.2.0.RELEASE</version>
    <scope>test</scope>
</dependency>

2.使用Junit提供的一个注解把原有的main方法替换了,替换成spring提供的@Runwith
3.告知spring的运行器,spring的ioc的创建是基于xml的还是基于注解的,并说明位置。
@ContextConfigration
locations:指定xml文件的位置,加上classpath关键字,表示在类路径下。
classes:自定注解所在的位置
在这里插入图片描述

总结

0.实体类

package com.hh.domain;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

//实体类
@Component("account")
public class Account {
    private Integer id;
    @Value("zhangsan")
    private String name;
    @Value("2000f")
    private Float money;


    public void setId(Integer id) {
        this.id = id;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setMoney(Float money) {
        this.money = money;
    }

    public Integer getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public Float getMoney() {
        return money;
    }

    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", money=" + money +
                '}';
    }
}

1.业务层接口

public interface AccountService {
    //查询所有
    List<Account> findAllAccount();
    //查询一个
    Account findAccountById(Integer id);
    //保存
    void saveAccount(Account account);
    //更新
    void updateAccount(Account account);
    //删除
    void deleteAccount(Integer id);
}

2.业务层实现类

@Service("accountService")
public class AccountServiceImpl implements AccountService{

    @Autowired
    private AccountDao accountDao;

    public List<Account> findAllAccount() {
        return accountDao.findAllAccount();
    }

    public Account findAccountById(Integer id) {
        return accountDao.findAccountById(id);
    }

    public void saveAccount(Account account) {
        accountDao.saveAccount(account);
    }

    public void updateAccount(Account account) {
        accountDao.updateAccount(account);
    }

    public void deleteAccount(Integer id) {
        accountDao.deleteAccount(id);
    }
}

3.持久层接口

//账户的持久层接口
public interface AccountDao {
    //查询所有
    List<Account> findAllAccount();
    //查询一个
    Account findAccountById(Integer id);
    //保存
    void saveAccount(Account account);
    //更新
    void updateAccount(Account account);
    //删除
    void deleteAccount(Integer id);
}

4.持久层实现类

//持久层实现类
@Repository("accountDao")
public class AccountDaoImpl implements AccountDao {
    @Autowired
    private QueryRunner runner;

    public List<Account> findAllAccount() {
        try {
            return runner.query("select * from account",new BeanListHandler<Account>(Account.class));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public Account findAccountById(Integer id) {
        try {
            return runner.query("select * from account where id=?",new BeanHandler<Account>(Account.class),id);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void saveAccount(Account account) {
        try {
            runner.update("insert into account(name,money) values(?,?)",account.getName(),account.getMoney());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void updateAccount(Account account) {
        try {
            runner.update("update account set name=?,money=? where id=?",account.getName(),account.getMoney(),account.getId());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void deleteAccount(Integer id) {
        try {
            runner.update("delete from account where id=?",id);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

5.SpringConfig配置主类

//该类是一个配置类,作用和bean.xml相同
@ComponentScan("com.hh")
@Import(JDBCConfig.class)
@PropertySource("classpath:jdbcConfig.properties")
public class SpringConfig {

    //用于创建一个QueryRunner对象
    @Bean(name="queryRunner")
    public QueryRunner createQueryRunner(DataSource dataSource){
        return new QueryRunner(dataSource);
    }
}

6.jdbcConfig.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/spring?serverTimezone=UTC
username=root
password=123

7.JDBCConfig配置副类

//和Spring连接数据库相关的配置类
public class JDBCConfig {
    @Value("${driver}")
    private String driver;
    @Value("${url}")
    private String url;
    @Value("${username}")
    private String username;
    @Value("${password}")
    private String password;

    //用于创建一个QueryRunner对象
    @Bean(name="queryRunner")
    public QueryRunner createQueryRunner(DataSource dataSource){
        return new QueryRunner(dataSource);
    }
    //创建一个DataSource对象
    @Bean(name="dataSource")
    public DataSource createDataSource() throws PropertyVetoException {
        ComboPooledDataSource ds =  new ComboPooledDataSource();
        ds.setDriverClass(driver);
        ds.setJdbcUrl(url);
        ds.setUser(username);
        ds.setPassword(password);
        return ds;
    }
}

8.测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class AccountServiceTest {
    @Autowired
    private AccountService service=null;
    @Autowired
    private Account account=null;

    @Test
    public void testFindAll(){
       List<Account> accounts =  service.findAllAccount();
       for(Account account :accounts){
           System.out.println(account);
       }
    }

    @Test
    public void testFindone(){
        Account account = service.findAccountById(3);
        System.out.println(account);
    }

    @Test
    public void testSave(){
        service.saveAccount(account);
    }

    @Test
    public void testUpdate(){
        account.setMoney(3000f);
        service.updateAccount(account);
    }

    @Test
    public void testDelete(){
        service.deleteAccount(4);
    }
}

赞(0) 打赏
未经允许不得转载:IDEA激活码 » Spring基于注解开发案例

相关推荐

  • 暂无文章

一个分享Java & Python知识的社区