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

2023-11-15

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 多例的
request WEB项目中,Spring创建一个Bean的对象,将对象存入到request域中
session WEB项目中,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);
    }
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • 为什么 i++ 不是原子的?

    Why is i Java 中不是原子的 为了更深入地了解 Java 我尝试计算线程中循环的执行频率 所以我用了一个 private static int total 0 在主课中 我有两个线程 主题 1 打印System out prin
  • Java中反射是如何实现的?

    Java 7 语言规范很早就指出 本规范没有详细描述反射 我只是想知道 反射在Java中是如何实现的 我不是问它是如何使用的 我知道可能没有我正在寻找的具体答案 但任何信息将不胜感激 我在 Stackoverflow 上发现了这个 关于 C
  • 在 java 类和 android 活动之间传输时音频不清晰

    我有一个android活动 它连接到一个java类并以套接字的形式向它发送数据包 该类接收声音数据包并将它们扔到 PC 扬声器 该代码运行良好 但在 PC 扬声器中播放声音时会出现持续的抖动 中断 安卓活动 public class Sen
  • 给定两个 SSH2 密钥,我如何检查它们是否属于 Java 中的同一密钥对?

    我正在尝试找到一种方法来验证两个 SSH2 密钥 一个私有密钥和一个公共密钥 是否属于同一密钥对 我用过JSch http www jcraft com jsch 用于加载和解析私钥 更新 可以显示如何从私钥 SSH2 RSA 重新生成公钥
  • 制作一个交互式Windows服务

    我希望我的 Java 应用程序成为交互式 Windows 服务 用户登录时具有 GUI 的 Windows 服务 我搜索了这个 我发现这样做的方法是有两个程序 第一个是服务 第二个是 GUI 程序并使它们进行通信 服务将从 GUI 程序获取
  • JAXb、Hibernate 和 beans

    目前我正在开发一个使用 Spring Web 服务 hibernate 和 JAXb 的项目 1 我已经使用IDE hibernate代码生成 生成了hibernate bean 2 另外 我已经使用maven编译器生成了jaxb bean
  • INSERT..RETURNING 在 JOOQ 中不起作用

    我有一个 MariaDB 数据库 我正在尝试在表中插入一行users 它有一个生成的id我想在插入后得到它 我见过this http www jooq org doc 3 8 manual sql building sql statemen
  • 控制Android的前置LED灯

    我试图在用户按下某个按钮时在前面的 LED 上实现 1 秒红色闪烁 但我很难找到有关如何访问和使用前置 LED 的文档 教程甚至代码示例 我的意思是位于 自拍 相机和触摸屏附近的 LED 我已经看到了使用手电筒和相机类 已弃用 的示例 但我
  • Mockito when().thenReturn 不必要地调用该方法

    我正在研究继承的代码 我编写了一个应该捕获 NullPointerException 的测试 因为它试图从 null 对象调用方法 Test expected NullPointerException class public void c
  • JRE 系统库 [WebSphere v6.1 JRE](未绑定)

    将项目导入 Eclipse 后 我的构建路径中出现以下错误 JRE System Library WebSphere v6 1 JRE unbound 谁知道怎么修它 右键单击项目 特性 gt Java 构建路径 gt 图书馆 gt JRE
  • 如何在 javadoc 中使用“<”和“>”而不进行格式化?

    如果我写
  • AWS 无法从 START_OBJECT 中反序列化 java.lang.String 实例

    我创建了一个 Lambda 函数 我想在 API 网关的帮助下通过 URL 访问它 我已经把一切都设置好了 我还创建了一个application jsonAPI Gateway 中的正文映射模板如下所示 input input params
  • 仅将 char[] 的一部分复制到 String 中

    我有一个数组 char ch 我的问题如下 如何将 ch 2 到 ch 7 的值合并到字符串中 我想在不循环 char 数组的情况下实现这一点 有什么建议么 感谢您花时间回答我的问题 Use new String value offset
  • Google App Engine 如何预编译 Java?

    App Engine 对应用程序的 Java 字节码使用 预编译 过程 以增强应用程序在 Java 运行时环境中的性能 预编译代码的功能与原始字节码相同 有没有详细的信息这是做什么的 我在一个中找到了这个谷歌群组消息 http groups
  • 无法捆绑适用于 Mac 的 Java 应用程序 1.8

    我正在尝试将我的 Java 应用程序导出到 Mac 该应用程序基于编译器合规级别 1 7 我尝试了不同的方法来捆绑应用程序 1 日食 我可以用来在 Eclipse 上导出的最新 JVM 版本是 1 6 2 马文 看来Maven上也存在同样的
  • 如何从指定日期获取上周五的日期? [复制]

    这个问题在这里已经有答案了 如何找出上一个 上一个 星期五 或指定日期的任何其他日期的日期 public getDateOnDay Date date String dayName 我不会给出答案 先自己尝试一下 但是 也许这些提示可以帮助
  • Java列表的线程安全

    我有一个列表 它将在线程安全上下文或非线程安全上下文中使用 究竟会是哪一个 无法提前确定 在这种特殊情况下 每当列表进入非线程安全上下文时 我都会使用它来包装它 Collections synchronizedList 但如果不进入非线程安
  • 使用 JMF 创建 RTP 流时出现问题

    我正处于一个项目的早期阶段 需要使用 RTP 广播DataStream创建自MediaLocation 我正在遵循一些示例代码 该代码目前在rptManager initalize localAddress 出现错误 无法打开本地数据端口
  • JGit 检查分支是否已签出

    我正在使用 JGit 开发一个项目 我设法删除了一个分支 但我还想检查该分支是否已签出 我发现了一个变量CheckoutCommand但它是私有的 private boolean isCheckoutIndex return startCo
  • 按日期对 RecyclerView 进行排序

    我正在尝试按日期对 RecyclerView 进行排序 但我尝试了太多的事情 我不知道现在该尝试什么 问题就出在这条线上适配器 notifyDataSetChanged 因为如果我不放 不会显示错误 但也不会更新 recyclerview

随机推荐