Spring学习之路 第二篇

Spring学习之路 第二篇

  • 在前一篇的入门基础上,我们继续学习Spring。
  • 本文涉及以下内容:
    1. 基于注解的IOC配置。
    2. 基于XML的IOC案例。
    3. 基于注解的IOC案例。
    4. 新注解说明(纯注解配置)。
    5. Spring整合Junit。

1. 基于注解的IOC配置
1.1 使用@Component 注解配置管理的资源

Component

  • 相当于:< bean id="" class="">
  • 作用:用于把当前类对象存入Spring容器中
  • 属性
    • value:用于指定bean的id。当我们不写时,它的默认值是当前类名,且首字母改成小写。
  1. 使用注解开发时,需要知道扫描哪些包的注解,修改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">
    
        <!--告知spring在创建容器时要扫描的包,配置所需要的标签不是在beans的约束中,而是
            context名称空间和约束中-->
        <context:component-scan base-package="fang"></context:component-scan>
    </beans>
  2. 编写需要存入Spring容器中的类:
    • Component不写value值,默认id为类名,且首字母小写。
    @Component
    public class AccountServiceImpl implements IAccountService {
        private IAccountDao accountDao;
    
        @Override
        public void saveAccount() {
            accountDao.saveAccount();
        }
    }
1.2 由Component注解衍生的注解
  • 他们三个注解都是针对一个的衍生注解,他们的作用及属性都是一模一样的。他们只不过是提供了更加明确的语义化。
  • @Controller:一般用于表现层的注解。
  • @Service:一般用于业务层的注解。
  • @Repository:一般用于持久层的注解。
1.3 @Autowired,注入数据
  • 他们的作用就和在xml配置文件中的bean标签中写一个< property>标签的作用是一样的
    作用:自动按照类型注入。只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配,就可以注入成功。若有多个时,会有问题。
    @Service("accountService")
    public class AccountServiceImpl implements IAccountService {
        
        @Autowired
        private IAccountDao accountDao;
        
        @Override
        public void saveAccount() {
            accountDao.saveAccount();
        }
    }
1.4 @Autowired,按照Bean的id注入
  • 在自动按照类型注入的基础之上,再按照 Bean 的 id 注入。它在给字段注入时不能独立使用,必须和@Autowired 一起使用;但是给方法参数注入时,可以独立使用。
  • 属性 value:指定 bean 的 id。
    @Service("accountService")
    public class AccountServiceImpl implements IAccountService {
    
        @Autowired
        @Qualifier("accountDao")
        private IAccountDao accountDao;
    
        @Override
        public void saveAccount() {
            accountDao.saveAccount();
        }
    }
1.5 @Resource,直接按照 Bean 的 id 注入
  • 可以替换@Autowired和@Qualifier
    作用:直接按照 Bean 的 id 注入。它也只能注入其他 bean 类型。
    属性: name:指定 bean 的 id。
  • 若在使用@Resource注解的时候,发现相应的包,这是JDK版本的问题,解决办法。在pom.xml中添加如下包:
    <dependency>
        <groupId>javax.annotation</groupId>
        <artifactId>javax.annotation-api</artifactId>
        <version>1.2</version>
    </dependency>
  • 使用Resource注解如下:
    @Service("accountService")
    public class AccountServiceImpl implements IAccountService {
    
        @Resource(name = "accountDao")
        private IAccountDao accountDao;
    
        @Override
        public void saveAccount() {
            accountDao.saveAccount();
        }
    }

1.5 @Value,注入基本数据类型和 String 类型数据的
  • 注意:@Autowired、@Qualifier、@Resource这三个注解只能注入其他的bean类型数据。而基本类型和String类型使用不了。需使用@Value注解。
  • 属性: value:用于指定值
  • 用于指定数据的值。它可以使用spring中SpEL(也就是spring的el表达式)SpEL的写法:${表达式}
1.5 @Scope,用于改变作用范围的。

作用:指定bean的作用范围。
属性:value:指定范围的值。

  • 取值:singleton prototype request session globalsession
  • 不写这个注解默认是singleton。
    @Service("accountService")
    @Scope("prototype")
    public class AccountServiceImpl implements IAccountService {
    
        @Resource(name = "accountDao")
        private IAccountDao accountDao;
    
        @Override
        public void saveAccount() {
            accountDao.saveAccount();
        }
    }
1.5 和生命周期相关的:(了解)
  • 相当于:< bean id="" class="" init-method="" destroy-method="" />
  • @PostConstruct:用于指定初始化方法。
  • @PreDestroy:用于指定销毁方法。
2. 基于XML的IOC案例

知识点:dbutils,c3p0连接池。

2.1 导包,编辑pom.xml
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>commons-dbutils</groupId>
        <artifactId>commons-dbutils</artifactId>
        <version>1.4</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.10</version>
    </dependency>
</dependencies>
2.2 编写配置文件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">
    
    <bean id="accountService" class="fang.service.impl.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"/>
    </bean>
    <bean id="accountDao" class="fang.dao.impl.AccountDaoImpl">
        <property name="runner" ref="runner"/>
    </bean> <!--增加scope="prototype"不是单例对象了-->
    <bean id="runner" 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/eesy"/>
        <property name="user" value="root"/>
        <property name="password" value="root"/>
    </bean>
</beans>
2.3 编写Account类,省略get、set等方法
public class Account implements Serializable {
    private Integer id;
    private String name;
    private Float money;
    ...
}
2.3 编写持久层接口和实现类

IAccountDao接口:

public interface IAccountDao {
    List<Account> findAllAccount();
    Account findAccountById(Integer accountId);
    void saveAccount(Account account);
    void updateAccount(Account account);
    void deleteAccount(Integer accountId);
}

AccountDaoImpl实现类:

public class AccountDaoImpl implements IAccountDao {
    private QueryRunner runner;

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

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

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

    @Override
    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);
        }
    }

    @Override
    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);
        }
    }

    @Override
    public void deleteAccount(Integer accountId) {
        try {
            runner.update("delete from account where id=?" ,accountId);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
2.4 编写业务层接口和实现类

业务层接口IAccountService:

public interface IAccountService {
    List<Account> findAllAccount();
    Account findAccountById(Integer accountId);
    void saveAccount(Account account);
    void updateAccount(Account account);
    void deleteAccount(Integer accountId);
}

业务层实现类AccountServiceImpl:

public class AccountServiceImpl implements IAccountService {
    private IAccountDao accountDao;

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

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

    @Override
    public Account findAccountById(Integer accountId) {
        return accountDao.findAccountById(accountId);
    }

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

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

    @Override
    public void deleteAccount(Integer accountId) {
        accountDao.deleteAccount(accountId);
    }
}
2.5 编写测试类AccountServiceTest:
public class AccountServiceTest {
    @Test
    public void testFindAll() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        IAccountService as = ac.getBean("accountService", IAccountService.class);
        List<Account> accounts = as.findAllAccount();
        for (Account account : accounts) {
            System.out.println(account);
        }
    }

    @Test
    public void testFindOne() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        IAccountService as = ac.getBean("accountService", IAccountService.class);
        Account account = as.findAccountById(1);
        System.out.println(account);
    }

    @Test
    public void testSave() {
        Account account = new Account();
        account.setName("fang");
        account.setMoney(12345F);
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        IAccountService as = ac.getBean("accountService", IAccountService.class);
        as.saveAccount(account);
    }

    @Test
    public void testUpdate() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        IAccountService as = ac.getBean("accountService", IAccountService.class);
        Account account = as.findAccountById(5);
        account.setMoney(10000F);
        as.updateAccount(account);
    }

    @Test
    public void testDelete() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        IAccountService as = ac.getBean("accountService", IAccountService.class);
        as.deleteAccount(5);
    }
}

3. 基于注解的IOC案例

前提:基于注解的IOC案例和基于XML的IOC案例几乎一样。

3.1 配置文件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">

    <!-- 告知spring在创建容器时要扫描的包 -->
    <context:component-scan base-package="fang"/>
    <!--配置QueryRunner-->
    <bean id="runner" 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/eesy"/>
        <property name="user" value="root"/>
        <property name="password" value="1234"/>
    </bean>
3.2 持久层的实现类AccountDaoImpl:
@Repository("accountDao")
public class AccountDaoImpl implements IAccountDao {
    @Autowired    
    private QueryRunner runner;
    ...
}
3.3 业务层的实现类AccountServiceImpl:
@Service("accountService")
public class AccountServiceImpl implements IAccountService{
    @Autowired    
    private IAccountDao accountDao;
    ...
}
4. 新注解说明(纯注解配置)
@Configuration:
  • 作用:指定当前类是一个配置类
  • 细节:当配置类作为AnnotationConfigApplicationContext对象创建的参数时,该注解可以不写。
@ComponentScan:
  • 作用:用于通过注解指定spring在创建容器时要扫描的包
  • value:它和basePackages的作用是一样的,都是用于指定创建容器时要扫描的包。
@Bean:
  • 作用:用于把当前方法的返回值作为bean对象存入spring的ioc容器中
  • name:用于指定bean的id。当不写时,默认值是当前方法的名称
  • 细节:当我们使用注解配置方法时,如果方法有参数,spring框架会去容器中查找有没有可用的bean对象。查找的方式和Autowired注解的作用是一样的。
@Import:
  • 作用:用于导入其他的配置类
  • value:用于指定其他配置类的字节码。
  • 当我们使用Import的注解之后,有Import注解的类就父配置类,而导入的都是子配置类.
@PropertySource:
  • 作用:用于指定properties文件的位置
  • value:指定文件的名称和路径。关键字:classpath,表示类路径下
@Qualifier:
  • 在参数上面用法如下。
4.1 编辑主配置类SpringConfiguration和副配置类JdbcConfig。
  1. SpringConfiguration(java/fang/config/SpringConfiguration.java):
  • @Configuration不写是因为在测试类中加载了SpringConfiguration.class的
    //@Configuration
    @ComponentScan("fang")
    @Import(jdbcConfig.class)
    @PropertySource("classpath:jdbcConfig.properties")
    public class SpringConfiguration {
    
    }
  1. JdbcConfig(java/fang/config/JdbcConfig.java):

    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;
        /**
         * 用于创建一个QueryRunner对象
         * @param dataSource
         * @return
         */
        @Bean(name="runner")
        @Scope("prototype")
        public QueryRunner createQueryRunner(@Qualifier("ds2") DataSource dataSource){
            return new QueryRunner(dataSource);
        }
        /**
         * 创建数据源对象
         * @return
         */
        @Bean(name="ds2")
        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);
            }
        }
        @Bean(name="ds1")
        public DataSource createDataSource1(){
            try {
                ComboPooledDataSource ds = new ComboPooledDataSource();
                ds.setDriverClass(driver);
                ds.setJdbcUrl("jdbc:mysql://localhost:3306/eesy02");
                ds.setUser(username);
                ds.setPassword(password);
                return ds;
            }catch (Exception e){
                throw new RuntimeException(e);
            }
        }
    }
    1. 测试类:
    • 若在AnnotationConfigApplicationContext也加入了JdbcConfig.class,那么 注解@Import(jdbcConfig.class)可不写。
    @Test
    public void testFindAll() {
        ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
        IAccountService as = ac.getBean("accountService", IAccountService.class);
        List<Account> accounts = as.findAllAccount();
        for (Account account : accounts) {
            System.out.println(account);
        }
    }

5. Spring整合Junit

Spring整合junit的配置:

  • 导入整合junit的jar包(坐标)
  • 使用Junit提供的一个注解把原有的main方法替换,替换成spring提供的
    • @Runwith
  • 告知spring的运行器,spring何让io创建是基于xml还是注解的,并且说明位置
    • @ContextConfiguration
      • locations:指定xml文件的位置,加上classpath关键字,表示在类路径下
      • classes:指定注解类所在位置
  • 当我们使用spring 5.x版本时,要求junit的jar包必须是4.12及以上。
  1. 在pom.xml中导入整合junit的jar包(坐标),junit版本也要改为4.12及以上。

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>
    
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
  2. 编辑测试类(基于注解的或xml的):

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = SpringConfiguration.class) //基于注解的
    //@ContextConfiguration(locations = "classpath:bean.xml") 基于xml的
    public class AccountServiceTest {
    
        @Autowired
        private IAccountService as;
    
        @Test
        public void testFindAll() {
            //ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
            //IAccountService as = ac.getBean("accountService", IAccountService.class);
            List<Account> accounts = as.findAllAccount();
            for (Account account : accounts) {
                System.out.println(account);
            }
        }
  • 到这里第二阶段的学习就结束啦。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值