spring养成计划 - spring基础 - (IOC_2)

spring的IOC是一个key,value(Map)结构

(一).常用的ioc注解
原xml方式的
<bean id="accountService" class="com.lc.service.impl.IAccountServiceImpl" scope="" init-method="" destroy-method="">
    <property name="" ref="" value=""></property>
</bean>
现在的配置方式,告知扫描位置
<?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.lc"></context:component-scan>
</beans>

1.用于创建对象的注解 bean
@Component将当前对象存入spring容器,value用于指定bean的id

@Component(value="accountService" )
public class AccountServiceImpl implements AccountService {

    private AccountDao accountDao = new AccountDaoImpl();
    @Override
    public void saveAccount() {
        accountDao.saveAccount();
    }
}

以下三个注解的作用和属性与@component一样,用于mvc架构,可以用@component替换掉
(1)@Controller 表现层
(2)@Service 业务层
(3)@Repository 持久层

2.用于注入数据的注解 property

  • @AutoWired 自动按照类型注入只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配(找不见就报错,如果找见多个相同类型,就会匹配key值一样的那个类型,都不一样就报错),就可以注入成功。
    位置:方法上或者变量上
    在这里插入图片描述
  • @Qualifier: value用于指定bean的id, 不能独立使用
    在按照类型注入的基础上,在按照名称注入,他在给成员注入时不能单独使用,但在给方法参数注入是可以。
  • @Primary:自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常
  • @Lazy(true) 表示延迟初始化
  • @Resource(name=“id”)
    直接使用key 进行注解
  • @value 用于注入基本类型和String类型的数据
    指定数据的值,可以配合SpEl(spring的el表达式 ${表达式})使用
@Value("normal")
private String normal; // 注入普通字符串

@Value("#{systemProperties['os.name']}")
private String systemPropertiesName; // 注入操作系统属性

@Value("#{ T(java.lang.Math).random() * 100.0 }")
private double randomNumber; //注入表达式结果

@Value("#{beanInject.another}")
private String fromAnotherBean; // 注入其他Bean属性:注入beanInject对象的属性another,类具体定义见下面
@Value("classpath:com/hry/spring/configinject/config.txt")
private Resource resourceFile; // 注入文件资源

@Value("http://www.baidu.com")
private Resource testUrl; // 注入URL资源

3.用于改变作用范围的注解 scope
@Scope(value=“prototype”) 用于指定bean的作用范围
value属性指定作用范围:singleton/prototype/session/global-session
默认是单例,修改成多例
4.和生命周期相关的注解 init_method,destory-metory
@preDestory 用于指定销毁方法
@PostConstruct 用于指定初始化方法
在这里插入图片描述

(二)使用xml方式实现表单的CRUD
<?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">
    <!--把对象创建交给beanFactory-->
    <!--service-->
    <bean id="accountService" class="com.lc.service.impl.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"></property>
    </bean>
    <!--dao-->
    <bean id="accountDao" class="com.lc.dao.impl.AccountDaoImpl">
        <property name="runner" ref="runner"></property>
    </bean>
    <!--配置数据QueryRunner 要有set方法-->
    <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.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/eesy"></property>
        <property name="user" value="root"></property>
        <property name="password" value="kwantler"></property>
    </bean>
</beans>
private QueryRunner runner;

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

    @Override
    public List<Account> findAll() {
        try {
            return runner.query("select * from account", new BeanListHandler<Account>(Account.class));
        } catch (SQLException e) {
            throw new RuntimeException("列表查询");
        }
    }
(三)改造基于注解ioc案例,使用纯注解的方式实现
  • 自建bean 改造成注解(非jar包中)
    dao
    在这里插入图片描述
    service
    在这里插入图片描述
<?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.lc"></context:component-scan>
    <!--配置数据QueryRunner-->
    <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.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/eesy"></property>
        <property name="user" value="root"></property>
        <property name="password" value="kwantler"></property>
    </bean>
</beans>
  • 完全去掉bean.xml
package config;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.commons.dbutils.QueryRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;
import java.beans.PropertyVetoException;

/**
 * 该类是一个配置类,他的作用和bean.xml一样
 * spring中的新注解
 * @Configuration 指当前类是一个配置类
 * @ComponentScan 用于通过注解指定spring在创建容器时要扫描的包
 *          属性:value 他和basePackages作用一样都是用来指定创建容器时要扫描的包
 *          等同于在xml中配置了<context:component-scan base-package="com.lc"></context:component-scan>
 *
 *  @Bean 将当前方法的返回值作为bean对象存入spring的容器中
 *  属性:name  ->用来指定bean的ID,默认是当前方法名称
 *  细节:当我们用注解来配置的话,如果有参数,spring会去容器中查找是否有可用的参数
 */
@Configuration
@ComponentScan("com.lc")
public class SpringConfiguration {
    /**
     * @Bean 将当前方法的返回值作为bean对象存入spring的容器中
     * 用于创建一个QueryRunner 对象
     * @param dataSource
     * @return
     */
    @Bean(name="runner")
    @Scope("prototype")
    public QueryRunner createQueryRunner(DataSource dataSource){
        return new QueryRunner(dataSource);
    }

    /**
     * 创建数据源对象
     * @return
     */
    @Bean(name="dataSource")
    public DataSource createDataSource(){
        try {
            ComboPooledDataSource ds = new ComboPooledDataSource();
            ds.setDriverClass("com.mysql.jdbc.Driver");
            ds.setJdbcUrl("jdbc:mysql://localhost:3306/eesy");
            ds.setUser("root");
            ds.setPassword("kwantler");
            return ds;
        } catch (PropertyVetoException e) {
            throw new RuntimeException("数据库连接失败");
        }
    }
}

@Test
    public void findAllTest() {
        ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
        AccountService accountService = ac.getBean("accountService", AccountService.class);
        List<Account> list = accountService.findAll();
        for (Account account:list) {
            System.out.println(account);
        }
    }
  • 多配制文件,读取Properties
package config;

import org.springframework.context.annotation.*;

/**
 * 该类是一个配置类,他的作用和bean.xml一样
 * spring中的新注解
 * @Configuration 指当前类是一个配置类
 *      细节:当配置对象是AnnotationConfigApplicationContext(SpringConfiguration.class)的参数时可以不写
 * @ComponentScan 用于通过注解指定spring在创建容器时要扫描的包
 *          属性:value 他和basePackages作用一样都是用来指定创建容器时要扫描的包
 *          等同于在xml中配置了<context:component-scan base-package="com.lc"></context:component-scan>
 *
 *  @Bean 将当前方法的返回值作为bean对象存入spring的容器中
 *  属性:name  ->用来指定bean的ID,默认是当前方法名称
 *  细节:当我们用注解来配置的话,如果有参数,spring会去容器中查找是否有可用的参数
 *  @import(JdbcConfig.class) 用于置指定其他配置类
 *  属性:value用来指定其他配置字节码,有import的类就是主(父)配置类,导入的都是子配置类
 * @PropertySource("classpath:jdbcConfig.properties") 用于指定properties文件的路径:classpath 表示类路径下
 */

//@Configuration
@ComponentScan("com.lc")
@Import(JdbcConfig.class)
@PropertySource("classpath:jdbcConfig.properties")
public class SpringConfiguration {

}

package config;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.commons.dbutils.QueryRunner;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;

import javax.sql.DataSource;
import java.beans.PropertyVetoException;

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 将当前方法的返回值作为bean对象存入spring的容器中
     * 用于创建一个QueryRunner 对象
     * @Scope("prototype") 注明是多例
     * @param dataSource
     * @return
     */
    @Bean(name="runner")
    @Scope("prototype")
    public QueryRunner createQueryRunner(DataSource dataSource){
        return new QueryRunner(dataSource);
    }

    /**
     * 创建数据源对象
     * @return
     */
    @Bean(name="dataSource")
    public DataSource createDataSource(){
        try {
            ComboPooledDataSource ds = new ComboPooledDataSource();
            ds.setDriverClass(driver);
            ds.setJdbcUrl(url);
            ds.setUser(username);
            ds.setPassword(password);
            return ds;
        } catch (PropertyVetoException e) {
            throw new RuntimeException("数据库连接失败");
        }
    }
}

在这里插入图片描述

(四)spring和junit整合
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.1.9.RELEASE</version>
    <scope>test</scope>
</dependency>
package com.lc.test;

import com.lc.domain.Account;
import com.lc.service.AccountService;
import config.SpringConfiguration;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.List;

/**
 * todo junit 单元测试
 * Spring 整合junit的配置要求junite4.1.2 以上版本
 * 1.导入Spring整合Junit的jar
 * 2.告知spring运行器,spring和ioc创建是基于xml还是注解的,并且说明位置
 *  @contextConfiguration locations:指定xml文件的位置:加上classpath表示在当前类路径下
 *                           classes: 指定注解类所在位置
 *
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration.class)
public class AccountServiceTest {
    @Autowired
    private AccountService accountService;

    @Test
    public void findAllTest() {

        List<Account> list = accountService.findAll();
        for (Account account:list) {
            System.out.println(account);
        }
    }

    @Test
    public void findByIdTest() {
        Account account= accountService.findById(1);
        System.out.println(account);
    }

    @Test
    public void saveAccountTest() {
        Account account = new Account();
        account.setName("王麻子");
        account.setMoney(12f);

        accountService.saveAccount(account);
    }

    @Test
    public void updateAccountTest() {
        Account account = new Account();
        account.setId(1);
        account.setName("王麻");
        account.setMoney(12f);

        accountService.updateAccount(account);
    }

    @Test
    public void deleteAccountTest() {
        accountService.deleteAccount(4);
    }
}

发布了17 篇原创文章 · 获赞 0 · 访问量 894

猜你喜欢

转载自blog.csdn.net/qq_36833168/article/details/103832721