Day65-Spring入门

4 篇文章 0 订阅

title: Day65-Spring入门
date: 2021-04-12 10:56:51
author: Liu_zimo


Spring

  • 工程构建(IDEA)

    1. 创建maven工程,(Spring aop/Spring ioc)

    2. 设置项目结构,Project Setting中 Project 设置Java JDK版本

    3. 模块中选择+,选择web,选中Spring aop工程,修改文件路径src\main\webapp

Spring简介

  • Spring是分层的Java SE/EE应用full-stack轻量级开源框架,以loC ( Inverse OfControl:反转控制)和AOP ( Aspect Oriented Programming:面向切面编程)为内核
  • 提供了展现层SpringMVC持久层Spring JDBCTemplate以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的JavaEE 企业应用开源框架。
  • 发展历史:Rod Johnson (Spring之父)
    • 1997年,IBM提出了EJB的思想
    • 1998年,SUN制定开发标准规范EJB1.0
    • 1999年,EJB1.1发布
    • 2001年,EJB2.0发布
    • 2003年,EJB2.1发布
    • 2006年,EJB3.0发布

Spring优势

  1. 方便解耦,简化开发
    通过Spring提供的loC容器,可以将对象间的依赖关系交由Spring进行控制,避免硬编码所造成的过度耦合。用户也不必再为单例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用
  2. AOP编程的支持
    通过Spring的AOP功能,方便进行面向切面编程,许多不容易用传统OOP实现的功能可以通过AOP轻松实现
  3. 声明式事务的支持
    可以将我们从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活的进行事务管理,提高开发效率和质量
  4. 方便程序的测试
    可以用非容器依赖的编程方式进行几乎所有的测试工作,测试不再是昂贵的操作,而是随手可做的事情
  5. 方便集成各种优秀框架
    Spring对各种优秀框架(Struts、Hibernate、Hessian、Quartz等)的支持
  6. 降低JavaEE API的使用难度
    Spring对JavaEEAPI(如JDBC、JavaMail、远程调用等)进行了薄薄的封装层,使这些API的使用难度大为降低
  7. Java源码是经典学习范例
    Spring的源代码设计精妙、结构清晰、匠心独用,处处体现着大师对Java设计模式灵活运用以及对Java技术的高深造诣。它的源代码无意是Java技术的最佳实践的范例

Spring体系结构

Spring体系结构

  • Core Container:核心容器
  • AOP、Aspects、lnstrumentation、Messaging
  • Data Access/lntegration:JDBC、ORM、OXM、JMS、Transactions
  • Web:WebSocket、Servlet、Web、Portlet

Spring入门

  • 原始开发步骤:

    UserDao userDao = new UserDaoImpl()

Spring开发步骤

  1. 导入Spring框架(jar包/坐标)
  2. 实现Dao接口和DaoImpl实现类
  3. 创建Spring核心XML配置文件
  4. 将DaoImpl实现类配置到XML文件中
  5. 通过Spring客户端.getBean(id标识)

Spring开发步骤

Spring配置文件

Bean标签基本配置

用于配置对象交由Spring来创建,默认情况下它调用的是类中的无参构造函数,如果没有无参构造函数则不能创建成功。

  • 基本属性:
    • id:Bean实例在Spring容器中的唯一标识
    • class:Bean的全限定名称
Bean标签范围配置
<bean id="userDao" class="com.zimo.dao.impl.UserDaoImpl" scope="singleton/prototype"></bean>
  • scope:指对象的作用范围,取值如下:
取值范围说明
singleton默认值,单例的
prototype多例的
requestWEB项目中,Spring创建一个Bean的对象,将对象存入到request域中
sessionWEB项目中,Spring创建一个Bean的对象,将对象存入到session域中
global sessionWEB项目中,应用在Portlet环境,如果没有Portlet环境那么globalSession相当于session
  1. 当scope的取值为singleton
    • Bean的实例化个数:1个
    • Bean的实例化时机:当Spring核心文件被加载时,实例化配置的Bean实例
    • Bean的生命周期:
      • 对象创建:当应用加载,创建容器时,对象就被创建了
      • 对象运行:只要容器在,对象一直活着
      • 对象销毁:当应用卸载,销毁容器时,对象就被销毁了
  2. 当scope的取值为prototype
    • Bean的实例化个数:多个
    • Bean的实例化时机:当调用getBean()方法时实例化Bean
      • 对象创建:当使用对象时,创建新的对象实例
      • 对象运行:只要对象在使用中,就一直活着
      • 对象销毁:当对象长时间不用时,被Java的垃圾回收器回收了
Bean生命周期配置
  • init-method:指定类中的初始化方法名称
  • destroy-method:指定类中销毁方法名称
<bean id="userDao" class="com.zimo.dao.impl.UserDaoImpl" init-method="init" destroy-method="destory"></bean>
Bean实例化三种方式
  • 无参构造方法实例化
  • 工厂静态方法实例化
  • 工厂实例方法实例化
package com.zimo.dao;
/**
 * @author Liu_zimo
 * @version v0.1 by 2021/4/12 14:21
 */
public interface UserDao {
    public void save();
}
  • 无参构造

    <bean id="userDao" class="com.zimo.dao.impl.UserDaoImpl" init-method="init" destroy-method="destory">

    package com.zimo.dao.impl;
    import com.zimo.dao.UserDao;
    /**
     * @author Liu_zimo
     * @version v0.1 by 2021/4/12 14:22
     */
    public class UserDaoImpl implements UserDao {
        @Override
        public void save() { System.out.println("save..."); }
        public void init(){ System.out.println("init..."); }
        public void destory(){ System.out.println("destory..."); }
    }
    
  • 工厂静态

    <bean id="userDao" class="com.zimo.factory.StaticFactory" factory-method="getUserDao"></bean>

    package com.zimo.factory;
    import com.zimo.dao.UserDao;
    import com.zimo.dao.impl.UserDaoImpl;
    /**
     * @author Liu_zimo
     * @version v0.1 by 2021/4/12 15:15
     */
    public class StaticFactory {
        public static UserDao getUserDao(){
            return new UserDaoImpl();
        }
    }
    
  • 工厂实例

    <!-- 先创建工厂实例,在通过工厂实例找到对象实例 -->
    <bean id="factory" class="com.zimo.factory.DynamicFactory"></bean>		
    <bean id="userDao" factory-bean="factory" factory-method="getUserDao"></bean>
    
    package com.zimo.factory;
    import com.zimo.dao.UserDao;
    import com.zimo.dao.impl.UserDaoImpl;
    /**
     * @author Liu_zimo
     * @version v0.1 by 2021/4/12 15:23
     */
    public class DynamicFactory {
        public UserDao getUserDao(){
            return new UserDaoImpl();
        }
    }
    
Bean的依赖注入分析

目前UserService实例和UserDao实例都存在与Spring容器中,当前的做法是在容器外部获得UserService实例和UserDao实例,然后在程序中进行结合

依赖注入1

因为UserService和UserDao都在Spring容器中,而最终程序直接使用的是UserService,所以可以在Spring容器中,将UserDao设置到UserService内部

依赖注入2

Bean的依赖注入
  • 概念:
    • 依赖注入(Dependency Injection):它是Spring框架核心IOC的具体实现
    • 在编写程序时,通过控制反转,把对象的创建交给了Spring,但是代码中不可能出现没有依赖的情况。IOC解耦只是降低他们的依赖关系,但不会消除。例如:业务层仍会调用持久层的方法。
    • 那这种业务层和持久层的依赖关系,在使用Spring之后,就让Spring来维护了。简单的说,就是坐等框架把持久层对象传入业务层,而不用我们自己去获取。
  • 方式:
    怎么将UserDao怎样注入到UserService内部呢?
    1. 构造方法
    2. set方法
  • Set方式实现(无法自己new对象)
package com.zimo.service.Impl;
import com.zimo.dao.UserDao;
import com.zimo.service.UserService;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 * @author Liu_zimo
 * @version v0.1 by 2021/4/12 15:31
 */
public class UserServiceImpl implements UserService {
    private UserDao userDao;
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    @Override
    public void Save() {
//        ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
//        UserDao userDao = (UserDao) app.getBean("userDao");
//        userDao.save();
        this.userDao.save();
    }
}
<bean id="userDao" class="com.zimo.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.zimo.service.Impl.UserServiceImpl">
    <property name="userDao" ref="userDao"></property>
</bean>
  • P命名空间注入本质也是set方法注入,但比起上述的set方法注入更加方便,主要体现在配置文件中,如下:

    首先,需要引入P命名空间:

    <?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:p="http://www.springframework.org/schema/p"	<!--p命名空间-->
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="userDao" class="com.zimo.dao.impl.UserDaoImpl"></bean>
        <bean id="userService" class="com.zimo.service.Impl.UserServiceImpl" p:userDao-ref="userDao" ></bean>
    </beans>
    
  • 构造方式
package com.zimo.service.Impl;
import com.zimo.dao.UserDao;
import com.zimo.service.UserService;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 * @author Liu_zimo
 * @version v0.1 by 2021/4/12 15:31
 */
public class UserServiceImpl implements UserService {
    private UserDao userDao;
    public UserServiceImpl(){}
    public UserServiceImpl(UserDao userDao) {
        this.userDao = userDao;
    }
    @Override
    public void Save() {
        this.userDao.save();
    }
}
<bean id="userDao" class="com.zimo.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.zimo.service.Impl.UserServiceImpl">
    <constructor-arg name="userDao" ref="userDao"></constructor-arg> <!--构造注入-->
</bean>
Bean的依赖注入的数据类型

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

  • 注入数据的三种数据类型
    • 普通数据类型:value
    • 引用数据类型:ref
    • 集合数据类型
package com.zimo.domain;
/**
 * @author Liu_zimo
 * @version v0.1 by 2021/4/12 16:43
 */
public class User {
    private String name;
    private String addr;
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getAddr() { return addr; }
    public void setAddr(String addr) { this.addr = addr; }
}
-------------------------------------------------------------------
package com.zimo.dao.impl;
import com.zimo.dao.UserDao;
/**
 * @author Liu_zimo
 * @version v0.1 by 2021/4/12 14:22
 */
public class UserDaoImpl implements UserDao {
    private String username;
    private int age;
    public void setUsername(String username) { this.username = username; }
    public void setAge(int age) { this.age = age; }
    public void setList(List<String> list) { this.list = list; }
    public void setUserMap(Map<String, User> userMap) { this.userMap = userMap; }
    public void setProperties(Properties properties) { this.properties = properties; }
    @Override
    public void save() { System.out.println("save..." + "username:" + username + ",age:" + age); }
}
  • 普通方式注入
<bean id="userDao" class="com.zimo.dao.impl.UserDaoImpl">
    <property name="username" value="张三"></property>
    <property name="age" value="18"></property>
</bean>
  • 集合注入
<bean id="userDao" class="com.zimo.dao.impl.UserDaoImpl">
    <property name="list">
        <list>
            <value>aaa</value><value>bbb</value><value>ccc</value>
        </list>
    </property>
    <property name="userMap">
        <map>
            <entry key="u1" value-ref="user1"></entry>
            <entry key="u1" value-ref="user2"></entry>
        </map>
    </property>
    <property name="properties">
        <props>
            <prop key="p1">pppp1</prop>
            <prop key="p2">pppp2</prop>
            <prop key="p3">pppp3</prop>
        </props>
    </property>
</bean>
<bean id="user1" class="com.zimo.domain.User">
    <property name="name" value="tom"/>
    <property name="addr" value="bj"/>
</bean>
<bean id="user2" class="com.zimo.domain.User">
    <property name="name" value="jery"/>
    <property name="addr" value="nj"/>
</bean>
<bean id="userService" class="com.zimo.service.Impl.UserServiceImpl">
    <constructor-arg name="userDao" ref="userDao"></constructor-arg>
</bean>
引入其他配置文件(分模块开发)

实际开发中,Spring的配置内容非常多,这就导致Spring配置很繁杂且体积很大,所以,可以将部分配置拆解到其他配置文件中,而在Spring主配置文件通过import标签进行加载

<import resource="applicationContext-user.xml"/>

知识点整理

  • <bean>标签
    • id属性:在容器中Bean实例的唯一标识,不允许重复
    • class属性:要实例化的Bean的全限定名
    • scope属性:Bean的作用范围,常用是singleton(默认)和prototype
    • <property>标签:属性注入
      • name属性:属性名称
      • value属性:注入的普通属性值
      • ref属性:注入的对象引用值
      • <list>标签
      • <map>标签
      • <properties>标签
    • <constructor-arg>标签
  • <import>标签:导入其他的spring的分文件

Spring相关API

  • applicationContext:接口类型,代表应用上下文,可以通过其实例获得Spring容器中的Bean对象
    1. ClassPathXmlApplicationContext
      它是从类的根路径下加载配置文件推荐使用这种
    2. FileSystemXmlApplicationContext
      它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。
    3. AnnotationConfigApplicationContext
      当使用注解配置容器对象时,需要使用此类来创建spring容器。它用来读取注解。

ApplicationContext继承体系

  • getBean()方法使用
UserDao userdao1 = (UserDao)app.getBean("userDao");
UserDao userdao2 = app.getBean(UserDao.class);
  • 其中,当参数的数据类型是字符串时,表示根据Bean的id从容器中获得Bean实例,返回是Object,需要强转
  • 当参数的数据类型是Class类型时,表示根据类型从容器中匹配Bean实例,当容器中相同类型的Bean有多个时,则此方法会报错。

Spring配置数据源

数据源(连接池)

  1. 数据源的作用:
    • 数据源(连接池)是提高程序性能如出现的
    • 事先实例化数据源,初始化部分连接资源
    • 使用连接资源时从数据源中获取
    • 使用完毕后将连接资源归还给数据源
    • 常见的数据源(连接池):DBCP、C3PO、BoneCP、Druid等
  2. 数据源手动创建
@Test
// 手动创建c3p0数据源
public void test1() throws Exception {
    ComboPooledDataSource dataSource = new ComboPooledDataSource();
    dataSource.setDriverClass("com.mysql.jdbc.Driver");
    dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
    dataSource.setUser("root");
    dataSource.setPassword("123456");
    Connection connection = dataSource.getConnection();
    connection.close();
}

@Test
// 手动创建Druid数据源
public void test2() throws Exception{
    DruidDataSource dataSource = new DruidDataSource();
    dataSource.setDriverClassName("com.mysql.jdbc.Driver");
    dataSource.setUrl("jdbc:mysql://localhost:3306/test");
    dataSource.setUsername("root");
    dataSource.setPassword("123456");
    DruidPooledConnection connection = dataSource.getConnection();
    connection.close();
}
@Test
// 手动创建c3p0数据源(加载properties配置文件)
public void test3() throws Exception {
    ResourceBundle rb = ResourceBundle.getBundle("jdbc");   // 读取配置文件
    ComboPooledDataSource dataSource = new ComboPooledDataSource();
    dataSource.setDriverClass(rb.getString("jdbc.driver"));
    dataSource.setJdbcUrl(rb.getString("jdbc.url"));
    dataSource.setUser(rb.getString("jdbc.username"));
    dataSource.setPassword(rb.getString("jdbc.password"));
    Connection connection = dataSource.getConnection();
    connection.close();
}
--------------------------------------------------------------------
# src/main/resource/jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=123456
  1. Spring配置数据源
    • 可以将DataSource的创建权交由Spring容器去完成
# src/main/resource/applicationContext.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="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
        <property name="user" value="root"></property>
        <property name="password" value="123456"></property>
    </bean>
</beans>
@Test
// spring容器产生数据源对象
public void test4() throws SQLException {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    DataSource dataSource = (ComboPooledDataSource) applicationContext.getBean("dataSource");
    Connection connection = dataSource.getConnection();
    connection.close();
}
抽取jdbc配置文件

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

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

  • 命名空间:xmIns:context="http://www.springframework.org/schema/context"
  • 约束路径:http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
<?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">
    <!--加载外部的properties文件-->
    <context:property-placeholder location="classpath:jdbc.properties"/>	<!--classpath:类加载路径-->

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"></property>
        <property name="jdbcUrl" value="${jdbc.url}"></property>
        <property name="user" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>
</beans>

Spring注解开发

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

Spring原始注解

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的销毁方法
  • 环境准备
package com.zimo.dao;
public interface UserDao {
    public void save();
}
----------------------------------------------------------------
package com.zimo.dao.impl;
import com.zimo.dao.UserDao;
public class UserDaoImpl implements UserDao {
    public void save() {
        System.out.println("save....");
    }
}
----------------------------------------------------------------
package com.zimo.service;
public interface UserService {
    public void save();
}
----------------------------------------------------------------
package com.zimo.service.impl;
import com.zimo.dao.UserDao;
import com.zimo.service.UserService;
public class UserServiceImpl implements UserService {
    private UserDao userDao;
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    public void save() {
        userDao.save();
    }
}
  • 传统实现方式
<?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="userDao" class="com.zimo.dao.impl.UserDaoImpl"></bean>
    <bean id="userService" class="com.zimo.service.impl.UserServiceImpl">
        <property name="userDao" ref="userDao"></property>
    </bean>
</beans>
package com.zimo.web;

import com.zimo.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 描述
 *
 * @author Liu_zimo
 * @version v0.1 by 2021/4/13 9:50
 */
public class UserController {
    public static void main(String[] args) {
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService bean = app.getBean(UserService.class);
        bean.save();
    }
}
  • 注解方式实现
package com.zimo.service.impl;
import com.zimo.dao.UserDao;
import com.zimo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;

// <bean id="userService" class="com.zimo.service.impl.UserServiceImpl"></bean>
// @Component("userService")
@Service("userService")	// 功能和@Component一样,可读性强一些
@Scope("singleton") // @Scope("prototype") 单例或多例
public class UserServiceImpl implements UserService {
    @Value("${jdbc.driver}")    // value属性注入普通数据类型
    private String driver;

    // <property name="userDao" ref="userDao"></property>
    @Autowired	// 按照数据类型从Spring容器中进行匹配的
    @Qualifier("userDao")	//是按照id值从容器中进行匹配的但是主要此处@Qualifier结合@Autowired一起使用
    private UserDao userDao;
    @Resource(name="userDao") //@Resource相当于@Qualifier+@Autowired
    private UserDao userDao1;
    // 使用注解事,可省略set方法
//    public void setUserDao(UserDao userDao) {
//        this.userDao = userDao;
//    }
    public void save() {
        userDao.save();
        userDao1.save();
    }
    @PostConstruct	// 构造后
    public void init(){
        System.out.println("init");
    }
    @PreDestroy		// 销毁前
    public void destory(){
        System.out.println("destory");
    }
}
--------------------------------------------------------------------
package com.zimo.dao.impl;
import com.zimo.dao.UserDao;
import org.springframework.stereotype.Component;

// <bean id="userDao" class="com.zimo.dao.impl.UserDaoImpl"></bean>
// @Component("userDao")
@Repository("userDao") 	// 功能一样,可读性强一些
public class UserDaoImpl implements UserDao {
    public void save() {
        System.out.println("save....");
    }
}
<?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">
    <!--加载外部的properties文件-->
    <context:property-placeholder location="classpath:jdbc.properties"/>	<!--classpath:类加载路径-->
    <!-- 配置组件扫描 -->
    <context:component-scan base-package="com.zimo"/>
</beans>
  • 测试代码
package com.zimo.web;
import com.zimo.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UserController {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService bean = app.getBean(UserService.class);
        bean.save();
        app.close();
    }
}

Spring新注解

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

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

/**
 * Spring核心配置文件
 *
 * @author Liu_zimo
 * @version v0.1 by 2021/4/13 14:18
 */
// 标志该类是Spring的核心配置类
@Configuration

// <context:component-scan base-package="com.zimo"/> 组件扫描配置
@ComponentScan("com.zimo")

// <import resource="" /> 引入数据源配置文件
@Import({DataSourceConfiguration.class})
public class SpringConfiguration {

}
package com.zimo.config;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;

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

/**
 * 数据源配置
 *
 * @author Liu_zimo
 * @version v0.1 by 2021/4/13 14:31
 */

// <context:property-placeholder location="classpath:jdbc.properties"/> 加载外部的properties文件
@PropertySource("classpath:jdbc.properties")
public class DataSourceConfiguration {
    @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("dataSource") // Spring会将当前方法的返回值以指定名称存储到Spring容器中
    public DataSource getDataSource() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setDriverClass(this.driver);	// 这边无法直接使用EL表达式注入
        dataSource.setJdbcUrl(this.url);
        dataSource.setUser(this.username);
        dataSource.setPassword(this.password);
        return dataSource;
    }
}
public static void main(String[] args) {
    ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfiguration.class);
    UserService bean = app.getBean(UserService.class);
    bean.save();
}

Spring整合Junit

  • 原始Junit测试Spring的问题
    • 在测试类中,每个测试方法都有以下两行代码:
ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfiguration.class);
UserService bean = app.getBean(UserService.class);
  • 这两行代码的作用是获取容器,如果不写的话,直接会提示空指针异常。所以又不能轻易删掉。
  • 上述问题解决思路
    • 让SpringJunit负责创建Spring容器,但是需要将配置文件的名称告诉它
    • 将需要进行测试Bean直接在测试类中进行注入

Spring集成Junit步骤

  1. 导入spring集成Junit的坐标
  2. 使用@Runwith注解替换原来的运行期
  3. 使用@contextconfiguration指定配置文件或配置类
  4. 使用@Autowired注入需要测试的对象
  5. 创建测试方法进行测试
package com.zimo.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

/**
 * Spring核心配置文件
 *
 * @author Liu_zimo
 * @version v0.1 by 2021/4/13 14:18
 */
// 标志该类是Spring的核心配置类
@Configuration

// <context:component-scan base-package="com.zimo"/> 组件扫描配置
@ComponentScan("com.zimo")

// <import resource="" /> 引入数据源配置文件
@Import({DataSourceConfiguration.class})
public class SpringConfiguration {
}
package com.zimo.config;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;
import javax.sql.DataSource;
import java.beans.PropertyVetoException;
/**
 * 数据源配置
 *
 * @author Liu_zimo
 * @version v0.1 by 2021/4/13 14:31
 */
// <context:property-placeholder location="classpath:jdbc.properties"/> 加载外部的properties文件
@PropertySource("classpath:jdbc.properties")
public class DataSourceConfiguration {
    @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("dataSource") // Spring会将当前方法的返回值以指定名称存储到Spring容器中
    public DataSource getDataSource() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setDriverClass(this.driver);
        dataSource.setJdbcUrl(this.url);
        dataSource.setUser(this.username);
        dataSource.setPassword(this.password);
        return dataSource;
    }
}
package com.zimo.test;

import com.zimo.config.SpringConfiguration;
import com.zimo.service.UserService;
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 javax.sql.DataSource;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {SpringConfiguration.class})
//@ContextConfiguration("classpath:applicationContext.xml")
public class SpringJunitTest {
    @Autowired
    private UserService userService;
    @Autowired
    private DataSource dataSource;
    @Test
    public void test1(){
        userService.save();
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柳子陌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值