java大数据开发训练营--Java Web 后端技术基础(下)之Spring IOC控制反转

Spring概述

1.1 Spring是什么

Spring是分层的 Java SE/EE应用 full-stack(全栈式) 轻量级开源框架

提供了表现层 SpringMVC持久层 Spring JDBC Template以及 业务层 事务管理等众多的企业级应用技术,还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的Java EE 企业应用开源框架。

两大核心:以 IOCInverse Of Control:控制反转)和 AOPAspect Oriented Programming:面向切面编程)为内核。

1.2 Spring优势 

1 )方便解耦,简化开发

Spring就是一个容器,可以将所有对象创建和关系维护交给Spring管理

什么是耦合度?对象之间的关系,通常说当一个模块(对象)更改时也需要更改其他模块(对象),这就是耦合,耦合度过高会使代码的维护成本增加。要尽量解耦

2 AOP 编程的支持

Spring提供面向切面编程,方便实现程序进行权限拦截,运行监控等功能。

3 )声明式事务的支持

通过配置完成事务的管理,无需手动编程

4 )方便测试,降低 JavaEE API 的使用

SpringJunit4支持,可以使用注解测试

5 )方便集成各种优秀框架

不排除各种优秀的开源框架,内部提供了对各种优秀框架的直接支持

二 初识IOC

2.1 概述

控制反转(Inverse Of Control不是什么技术,而是一种设计思想。它的目的是指导我们设计出更加松耦合的程序。

控制:在 java 中指的是对象的控制权限(创建、销毁)
反转:指的是对象控制权由原来 由开发者在类中手动控制 反转到 Spring 容器控制

举个栗子  

* 传统方式

之前我们需要一个userDao实例,需要开发者自己手动创建 new UserDao();

* IOC 方式

现在我们需要一个userDao实例,直接从springIOC容器获得,对象的创建权交给了spring控制

Spring快速入门

3.1 介绍

需求 :借助 spring IOC 实现 service 层与 dao 层代码解耦合
步骤分析 
1. 创建 java 项目,导入 spring 开发基本坐标
2. 编写 Dao 接口和实现类
3. 创建 spring 核心配置文件
4. spring 配置文件中配置 UserDaoImpl
5. 使用 spring 相关 API 获得 Bean 实例
3.2 实现

1)创建java项目,导入spring开发基本坐标

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>

2)编写Dao接口和实现类

public interface UserDao {
    public void save();
}
public class UserDaoImpl implements UserDao {
    public void save() {
        System.out.println("调用save");
    }
}

 3)创建spring核心配置文件

<?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">


</beans>

4)在spring配置文件中配置 UserDaoImpl

<!--添加到beans标签里-->
<bean id="userDao" class="com.bigload.daoImpl.UserDaoImpl"/>

5)使用spring相关API获得Bean实例

public class springTest {
    @Test
    public void test1(){
        ClassPathXmlApplicationContext con = new ClassPathXmlApplicationContext("appLicationContext.xml");
        /*根据Bean的id和类型获得Bean实例*/
        UserDao userDao = con.getBean("userDao",UserDao.class);
        userDao.save();

    }
}

3.3 知识小结

Spring 的开发步骤
1. 导入坐标
2. 创建 Bean
3. 创建 applicationContext.xml
4. 在配置文件中进行 Bean 配置
5. 创建 ApplicationContext 对象,执行 getBean

Spring相关API

4.1 API继承体系介绍

SpringAPI体系异常庞大,我们现在只关注两个BeanFactoryApplicationContext

 

4.2 BeanFactory

BeanFactory IOC 容器的核心接口,它定义了 IOC 的基本功能。
特点:在第一次调用 getBean() 方法时,创建指定对象的实例
BeanFactory beanFactory = new XmlBeanFactory ( new ClassPathResource ( "applicationContext.xml" ));

4.3 ApplicationContext

代表应用上下文对象,可以获得 spring IOC 容器的 Bean 对象。
特点:在 spring 容器启动时,加载并创建所有对象的实例

常用实现类

1. ClassPathXmlApplicationContext

它是从类的根路径下加载配置文件 推荐使用这种。

2. FileSystemXmlApplicationContext

它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。

3. AnnotationConfigApplicationContext

当使用注解配置容器对象时,需要使用此类来创建 spring 容器。它用来读取注解。

ApplicationContext app = new ClassPathXmlApplicationContext ( "applicationContext.xml" );
 

常用方法

1. Object getBean ( String name );

根据Beanid从容器中获得Bean实例,返回是Object,需要强转。

2. < T > T getBean ( Class < T > requiredType );

根据类型从容器中匹配Bean实例,当容器中相同类型的Bean有多个时,则此方法会报错。

3. < T > T getBean ( String name , Class < T > requiredType );

根据Beanid和类型获得Bean实例,解决容器中相同类型Bean有多个情况。

Spring配置文件

5.1 Bean标签基本配置  

<bean id = "" class = "" ></bean>
* 用于配置对象交由 Spring 来创建。
* 基本属性:

idBean实例在Spring容器中的唯一标识

classBean的全限定名

* 默认情况下它调用的是类中的 无参构造函数,如果没有无参构造函数则不能创建成功。

5.2 Bean标签范围配置 

<bean id = "" class = "" scope = "" ></bean>

scope属性指对象的作用范围,取值如下:

取值范围
说明
singleton默认值,单例的
prototype多例的
requestWEB项目中,Spring创建一个Bean的对象,将对象存入到request域中
sessionWEB项目中,Spring创建一个Bean的对象,将对象存入到session域中
global
session
WEB 项目中,应用在 Portlet 环境,如果没有 Portlet 环境那么 globalSession 相当于 session
1. scope 的取值为 singleton

Bean的实例化个数:1

Bean的实例化时机:当Spring核心文件被加载时,实例化配置的Bean实例

Bean的生命周期:

对象创建:当应用加载,创建容器时,对象就被创建了

对象运行:只要容器在,对象一直活着

对象销毁:当应用卸载,销毁容器时,对象就被销毁了

2. scope 的取值为 prototype

Bean的实例化个数:多个

Bean的实例化时机:当调用getBean()方法时实例化Bean

Bean的生命周期:

对象创建:当使用对象时,创建新的对象实例

对象运行:只要对象在使用中,就一直活着

对象销毁:当对象长时间不用时,被 Java 的垃圾回收器回收了

5.3 Bean生命周期配置  

<bean id = "" class = "" scope = "" init-method = "" destroy-method = "" ></bean>

* init-method:指定类中的初始化方法名称

* destroy-method:指定类中销毁方法名称

5.4 Bean实例化三种方式

  • 无参构造方法实例化
  • 工厂静态方法实例化
  • 工厂普通方法实例化

5.4.1 无参构造方法实例化

它会根据默认无参构造方法来创建类对象,如果bean没有默认无参构造函数,将会创建失败

<bean id="userDao" class="com.lagou.dao.impl.UserDaoImpl"/>

5.4.2 工厂静态方法实例化

应用场景
依赖的 jar 包中有个 A 类, A 类中有个静态方法 m1 m1 方法的返回值是一个 B对象。如果我们频繁使用B 对象,此时我们可以将 B 对象的创建权交给 spring IOC 容器,以后我们在使用 B 对象时,无需调用 A类中的 m1 方法,直接从 IOC 容器获得。
public class StaticFactoryBean { 
    public static UserDao createUserDao(){ 
        return new UserDaoImpl(); 
    } 
}
<bean id="userDao" class="com.lagou.factory.StaticFactoryBean" factory-method="createUserDao" />

5.4.3 工厂普通方法实例化

应用场景
依赖的 jar 包中有个 A 类, A 类中有个普通方法 m1 m1 方法的返回值是一个 B对象。如果我们频繁使用 B对象, 此时我们可以将 B 对象的创建权交给 spring IOC 容器,以后我们在使用 B 对象时,无需调用 A 类中的m1 方法,直接从 IOC 容器获得。
public class DynamicFactoryBean { 
    public UserDao createUserDao(){ 
        return new UserDaoImpl(); 
    } 
}
<bean id="dynamicFactoryBean" class="com.lagou.factory.DynamicFactoryBean"/> 
<bean id="userDao" factory-bean="dynamicFactoryBean" factory-method="createUserDao"/>

5.5 Bean依赖注入概述

依赖注入 DIDependency Injection:它是 Spring 框架核心 IOC 的具体实现。

在编写程序时,通过控制反转,把对象的创建交给了 Spring,但是代码中不可能出现没有依赖的情况。IOC 解耦只是降低他们的依赖关系,但不会消除。例如:业务层仍会调用持久层的方法。

那这种业务层和持久层的依赖关系,在使用 Spring 之后,就让 Spring 来维护了。简单的说,就是过框架把持久层对象传入业务层,而不用我们自己去获取。

5.6 Bean依赖注入方式

5.6.1 构造方法

UserServiceImpl 中创建有参构造
public interface UserService {
    public void save();
}
public class UserServiceImpl implements UserService {
    private UserDao userDao;
    public UserServiceImpl(UserDao userDao){
        this.userDao=userDao;
    }
    @Override
    public void save() {
        userDao.save();;
    }
}

配置Spring容器调用有参构造时进行注入

    <bean id="userDao" class="com.bigload.daoImpl.UserDaoImpl"/>
    <bean id="userService" class="com.bigload.daoImpl.UserServiceImpl">
        <constructor-arg name="userDao" ref="userDao"/>
    </bean>

5.6.2 set方法

UserServiceImpl 中创建 set 方法
public class UserServiceImpl implements UserService {

    private UserDao userDao;
//    public UserServiceImpl(UserDao userDao){
//        this.userDao=userDao;
//    }
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void save() {
        userDao.save();;
    }
}
配置 Spring 容器调用 set 方法进行注入
    <bean id="userService" class="com.bigload.daoImpl.UserServiceImpl">
        <property name="userDao" ref="userDao"/>
    </bean>

5.6.3 P命名空间注入

P 命名空间注入本质也是 set 方法注入,但比起上述的 set方法注入更加方便,主要体现在配置文件中,如下:
首先,需要引入 P 命名空间:
xmlns:p="http://www.springframework.org/schema/p"

其次,需要修改注入方式:

    <bean id="userService" class="com.bigload.daoImpl.UserServiceImpl" p:userDao-ref="userDao">
    </bean>

5.7 Bean依赖注入的数据类型

上面操作,都是注入Bean对象,除了对象的引用可以注入,普通数据类型和集合都可以在容器中进行注入。

注入数据的三种数据类型

1. 普通数据类型

2. 引用数据类型

3. 集合数据类型

其中引用数据类型,此处就不再赘述了,之前的操作都是对UserDao对象的引用进行注入的。下面将以set方法注入为例,演示普通数据类型和集合数据类型的注入。

5.7.1 注入普通数据类型

public class User {
    private String name;
    private String age;

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

    public void setAge(String age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age='" + age + '\'' +
                '}';
    }
}
    <bean id="user" class="com.bigload.domain.User">
        <property name="age" value="18"/>
        <property name="name" value="bigload"/>
    </bean>

5.7.2 注入集合数据类型

public class UserDaoImpl implements UserDao {
    /*list集合注入*/
    private List alist;
    public void setAlist(List alist) {
        this.alist = alist;
    }
    /*set集合注入*/
    private Set aset;
    public void setAset(Set aset) {
        this.aset = aset;
    }
    /*array数组注入*/
    private Object[] array;
    public void setArray(Object[] array) {
        this.array = array;
    }
    /*map集合注入*/
    private Map<String, Object> amap;
    public void setMap(Map<String, Object> map) { this.amap = map; }
    /*Properties配置注入*/
    private Properties properties;
    public void setProperties(Properties properties) { this.properties = properties; }

    public void save() {
        System.out.println(alist);
        System.out.println(aset);
        for (Object o : array) {
            System.out.println(o);
        }
        System.out.println(amap);
        System.out.println(properties);
        System.out.println("调用save");
    }
}
    <bean id="user" class="com.bigload.domain.User">
        <property name="age" value="18"/>
        <property name="name" value="bigload"/>
    </bean>
    <bean id="userDao" class="com.bigload.daoImpl.UserDaoImpl">
        <!--list集合注入-->
        <property name="alist" >
            <list>
                <value>alist</value>
                <value>123</value>
                <ref bean="user"></ref>
            </list>
        </property>
        <!--array数组注入-->
        <property name="array">
            <array>
                <value>array</value>
                <value>123</value>
                <ref bean="user"></ref>
            </array>
        </property>
        <!--set集合注入-->
        <property name="aset">
            <list>
                <value>aset</value>
                <value>123</value>
                <ref bean="user"></ref>
            </list>
        </property>
        <!--map集合注入-->
        <property name="map">
            <map>
                <entry key="123" value="123"></entry>
                <entry key="user" value-ref="user"></entry>
            </map>
        </property>
        <!--properties配置注入-->
        <property name="properties">
            <props>
                <prop key="k1">v1</prop>
                <prop key="k2">v2</prop>
                <prop key="k3">v3</prop>
            </props>
        </property>
    </bean>

5.8 配置文件模块化

实际开发中,Spring的配置内容非常多,这就导致Spring配置很繁杂且体积很大,所以,可以将部分配置拆解到其他配置文件中,也就是所谓的配置文件模块化

1 )并列的多个配置文件
ApplicationContext act = new ClassPathXmlApplicationContext ( "beans1.xml" , "beans2.xml" , "..." );
2 )主从配置文件
<import resource = "applicationContext-xxx.xml" />
注意:

同一个xml中不能出现相同名称的bean,如果出现会报错

多个xml如果出现相同名称的bean,不会报错,但是后加载的会覆盖前加载的bean

5.9 知识小结

Spring 的重点配置
<bean> 标签:创建对象并放到 spring IOC 容器

id属性:在容器中Bean实例的唯一标识,不允许重复

class属性:要实例化的Bean的全限定名

scope属性:Bean的作用范围,常用是Singleton(默认)prototype

<constructor-arg> 标签:属性注入
使用构造方法生成

name属性:属性名称

value属性:注入的普通属性值

ref属性:注入的对象引用值

<property> 标签:属性注入
使用set成员变量方法,例setAge()

name属性:属性名称

value属性:注入的普通属性值

ref属性:注入的对象引用值

<list>

<set>

<array>

<map>

<props>

<import> 标签 : 导入其他的 Spring 的分文件

DbUtilsIOC实战)  

6.1 DbUtils是什么?

6.2 Springxml整合DbUtils

6.2.1 介绍

需求

基于Springxml配置实现账户的CRUD案例

步骤分析  
1. 准备数据库环境
2. 创建 java 项目,导入坐标
3. 编写 Account 实体类
4. 编写 AccountDao 接口和实现类
5. 编写 AccountService 接口和实现类
6. 编写 spring 核心配置文件
7. 编写测试代码

6.2.2 实现

1 )准备数据库环境
CREATE DATABASE `spring_db`;
USE `spring_db`;
CREATE TABLE `account` (
`id` int ( 11 ) NOT NULL AUTO_INCREMENT,
`name` varchar ( 32 ) DEFAULT NULL ,
`money` double DEFAULT NULL ,
PRIMARY KEY (`id`)
) ;
insert into `account`(`id`,`name`,`money`) values ( 1 , 'tom' , 1000 ),
( 2 , 'jerry' , 1000 );

 2)创建java项目,导入坐标

<dependencies>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.47</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.9</version>
    </dependency>
    <dependency>
        <groupId>commons-dbutils</groupId>
        <artifactId>commons-dbutils</artifactId>
        <version>1.6</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.1.5.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
</dependencies>

3)编写Account实体类

public class Account {
    private Integer id;
    private String name;
    private Double money;
    //get,set,tostring省略没展示
}

4)编写AccountDao接口和实现类

public interface AccountDao {
    public List<Account> findAll();

    public Account findById(Integer id);

    public void save(Account account);

    public void update(Account account);

    public void delete(Integer id);
}
public class AccountDaoImpl implements AccountDao {
    private QueryRunner queryRunner;

    public void setQueryRunner(QueryRunner queryRunner) {
        this.queryRunner = queryRunner;
    }

    /*查询所有*/
    public List<Account> findAll() {
        String sql = "select * from account";
        List<Account> accountList=null;
        try {
            accountList= queryRunner.query(sql, new BeanListHandler<Account>(Account.class));

        } catch (SQLException e) {
            e.printStackTrace();
        }
        return accountList;
    }
    /*查询指定id*/
    public Account findById(Integer id) {
        String sql="select * from account where id =?";
        Account account=null;
        try {
            account = queryRunner.query(sql, new BeanHandler<Account>(Account.class),id);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return account;
    }
    /*保存*/
    public void save(Account account) {
        String sql="insert into account values(null,?,?)";
        try {
            queryRunner.update(sql,account.getName(),account.getMoney());
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    /*更新*/
    public void update(Account account) {
        String sql="update account set name=?,money=? where id=?";
        try {
            queryRunner.update(sql,account.getName(),account.getMoney(),account.getId());
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    /*删除*/
    public void delete(Integer id) {
        String sql="delete from account where id=?";
        try {
            queryRunner.update(sql,id);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

5)编写AccountService接口和实现类

public interface AccountService {
    public List<Account> findAll();

    public Account findById(Integer id);

    public void save(Account account);

    public void update(Account account);

    public void delete(Integer id);
}
public class AccountServiceImpl implements AccountService {

    private AccountDao accountDao;

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

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

    @Override
    public Account findById(Integer id) {
        return accountDao.findById(id);
    }

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

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

    @Override
    public void delete(Integer id) {
        accountDao.delete(id);
    }
}

6)编写spring核心配置文件

    <!--数据库配置-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/spring_db"></property>
        <property name="username" value="root"></property>
        <property name="password" value="wasdfgh1"></property>
    </bean>

    <bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner">
        <constructor-arg name="ds" ref="dataSource"/>
    </bean>
    <bean id="accountDao" class="com.bigload.daoImpl.AccountDaoImpl">
        <property name="queryRunner" ref="queryRunner"/>
    </bean>
    <bean id="accountService" class="com.bigload.daoImpl.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"/>
    </bean>

7)编写测试代码

    @Test
    public void test2(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("appLicationContext.xml");
        AccountService accountService = context.getBean("accountService", AccountService.class);
        /*查询所有*/
        List<Account> accounts = accountService.findAll();
        System.out.println(accounts);
        /*查询指定id*/
//        Account byId = accountService.findById(2);
//        System.out.println(byId);
        /*创建一个account实例*/
//        Account account = new Account();
//        account.setName("lucy");
//        account.setMoney(200000.0);
        /*保存account*/
//        accountService.save(account);
//        account.setMoney(200.0);
//        account.setId(3);
        /*修改*/
//        accountService.update(account);
        /*删除*/
//        accountService.delete(3);

    }

8)抽取jdbc配置文件  

applicationContext.xml加载jdbc.properties配置文件获得连接信息。

首先,需要引入context命名空间和约束路径:

* 命名空间:

xmlns:context="http://www.springframework.org/schema/context"

* 约束路径:

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context.xsd

applicationContext.xml 

    <context:property-placeholder location="jdbc.properties"/>
    <!--数据库配置-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

 jdbc.properties

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_db
jdbc.username=root
jdbc.password=123

Spring注解开发

Spring是轻代码而重配置的框架,配置比较繁重,影响开发效率,所以注解开发是一种趋势,注解代替xml配置文件可以简化配置,提高开发效率。

7.1 Spring常用注解

7.1.1 介绍

Spring 常用注解主要是替代 <bean> 的配置
 
注解
说明
@Component使用在类上用于实例化Bean
@Controller使用在web层类上用于实例化Bean
@Service使用在service层类上用于实例化Bean
@Repository使用在dao层类上用于实例化Bean
@Autowired使用在字段上用于根据类型依赖注入
@Qualifier结合@Autowired一起使用,根据名称进行依赖注入
@Resource相当于@Autowired+@Qualifier,按照名称进行注入
@Value注入普通属性
@Scope标注Bean的作用范围
@PostConstruct使用在方法上标注该方法是Bean的初始化方法
@PreDestroy使用在方法上标注该方法是Bean的销毁方法
说明:
JDK11 以后完全移除了 javax 扩展导致不能使用 @resource 注解
需要 maven 引入依赖
<dependency>
    <groupId> javax.annotation </groupId>
    <artifactId> javax.annotation-api </artifactId>
    <version> 1.3.2 </version>
</dependency>
注意

使用注解进行开发时,需要在applicationContext.xml中配置组件扫描,作用是指定哪个包及其子包下的Bean需要进行扫描以便识别使用注解配置的类、字段和方法。  

<!-- 注解的组件扫描 -->
<context:component-scan base-package = "com.lagou" ></context:component-scan>

7.1.2 实现

1 Bean 实例化( IOC
<bean id="userDao" class="com.bigload.daoImpl.UserDaoImpl"></bean>

 使用@Compont@Repository标识UserDaoImpl需要Spring进行实例化。

//@Component(value = "userDao")
@Repository(value = "userDao")
//@Repository // 如果没有写value属性值,Beanid为:类名首字母小写 
public class UserDaoImpl implements UserDao {...} 

2)属性依赖注入(DI

<bean id="userService" class="com.bigload.daoImpl.UserServiceImpl">
    <property name="userDao" ref="userDao"/>
</bean>

使用@Autowired或者@Autowired+@Qulifier或者@Resource进行userDao的注入

@Service(value = "userService")
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao userDao;


    @Override
    public void save() {
        userDao.save();;
    }
}

3@Value

使用 @Value 进行字符串的注入,结合 SPEL 表达式获得配置参数
@Service
public class UserServiceImpl implements UserService {
    @Value ( " 注入普通数据 " )
    private String str ;
    @Value ( "${jdbc.driver}" )
    private String driver ;
 /*list集合注入*/
 @Value("#{{'ab',1,'c'}}")
 private List alist;
}

4@Scope

<bean scope=""/> 

使用@Scope标注Bean的范围

 

@Service
@Scope ( "singleton" )
public class UserServiceImpl implements UserService {...}
 

5Bean生命周期

<bean init-method="init" destroy-method="destory" />  

使用@PostConstruct标注初始化方法,使用@PreDestroy标注销毁方法

@PostConstruct
public void init(){
    System.out.println("初始化方法....");
}
@PreDestroy
public void destroy(){
    System.out.println("销毁方法.....");
}

7.2 Spring常用注解整合DbUtils

步骤分析
1. 拷贝 xml 配置项目,改为注解配置项目
2. 修改 AccountDaoImpl 实现类
3. 修改 AccountServiceImpl 实现类
4. 编写测试代码 
 
1. 拷贝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
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
>
    <context:property-placeholder location="jdbc.properties"/>
    <!--数据库配置-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

    <bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner">
        <constructor-arg name="ds" ref="dataSource"/>
    </bean>


    <!--注解的组件扫描-->
    <context:component-scan base-package="com.bigload"></context:component-scan>

</beans>

2. 修改AccountDaoImpl实现类

@Component("accountDao")
public class AccountDaoImpl implements AccountDao {

    @Autowired
    private QueryRunner queryRunner;

        ...

 }

3. 修改AccountServiceImpl实现类
@Component("accountService")
public class AccountServiceImpl implements AccountService {

    @Autowired
    private AccountDao accountDao;

         ...

}

4. 编写测试代码
    @Test
    public void test2(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("appLicationContext.xml");
        AccountService accountService = context.getBean("accountService", AccountService.class);
        /*查询所有*/
        List<Account> accounts = accountService.findAll();
        System.out.println(accounts);
    }

7.3 Spring新注解

使用上面的注解还不能全部替代 xml 配置文件,还需要使用注解替代的配置如下:
* 非自定义的 Bean 的配置: <bean>
* 加载 properties 文件的配置: <context:property-placeholder>
* 组件扫描的配置: <context:component-scan>
* 引入其他文件: <import>
注解
说明
@Configuration用于指定当前类是一个Spring 配置类,当创建容器时会从该类上加载注解
@Bean使用在方法上,标注将该方法的返回值存储到 Spring 容器中
@PropertySource用于加载 properties 文件中的配置
@ComponentScan用于指定 Spring 在初始化容器时要扫描的包
@Import用于导入其他配置类

7.4 Spring纯注解整合DbUtils

步骤分析
1. 编写 Spring 核心配置类
2. 编写数据库配置信息类
3. 编写测试代码
1. 编写Spring核心配置类
@Configuration
@ComponentScan("com.bigload")
@Import(dataSourceConfig.class)
public class SpringConfig {

    @Bean("queryRunner")
    public QueryRunner queryRunner(@Autowired DataSource dataSource){
        return new QueryRunner(dataSource);
    }
}

2. 编写数据库配置信息类

@Configuration
@PropertySource("classpath:jdbc.properties")
public class dataSourceConfig {

    @Value("${jdbc.driverClassName}")
    private String driverClassName;

    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;

    @Bean("dataSource")
    public DataSource dataSource(){
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setDriverClassName(driverClassName);
        druidDataSource.setUrl(url);
        druidDataSource.setUsername(username);
        druidDataSource.setPassword(password);
        return druidDataSource;
    }
}

3. 编写测试代码

    @Test
    public void test3(){
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        AccountService accountService = context.getBean("accountService", AccountService.class);
        List<Account> all = accountService.findAll();
        System.out.println(all);
    }

Spring整合Junit

8.1普通Junit测试问题

在普通的测试类中,需要开发者手动加载配置文件并创建Spring容器,然后通过Spring相关API获得Bean实例;如果不这么做,那么无法从容器中获得对象。

我们可以让SpringJunit负责创建Spring容器来简化这个操作,开发者可以直接在测试类注入Bean实例;但是需要将配置文件的名称告诉它

8.2 Spring整合Junit

步骤分析
1. 导入 spring 集成 Junit 的坐标
2. 使用 @Runwith 注解替换原来的运行器
3. 使用 @ContextConfiguration 指定配置文件或配置类
4. 使用 @Autowired 注入需要测试的对象
5. 创建测试方法进行测试
1. 导入spring集成Junit的坐标
<!--此处需要注意的是,spring5 及以上版本要求 junit 的版本必须是 4.12 及以上--> 
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.1.5.RELEASE</version>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>
2. 使用@Runwith注解替换原来的运行器
3. 使用@ContextConfiguration指定配置文件或配置类
4. 使用@Autowired注入需要测试的对象
5. 创建测试方法进行测试
/*2. 使用@Runwith注解替换原来的运行器 */
@RunWith(SpringJUnit4ClassRunner.class)
/*3. 使用@ContextConfiguration指定配置文件或配置类*/
@ContextConfiguration(classes = {SpringConfig.class})
public class SpringJunitTest {

    /*4. 使用@Autowired注入需要测试的对象*/
    @Autowired
    private AccountService accountService;

    /*5. 创建测试方法进行测试*/
    @Test
    public void test1(){
        List<Account> all = accountService.findAll();
        System.out.println(all);
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值