【施工中】Spring5

0、楔子

  • 为什么学Spring?
    微服务成为当前项目架构和开发的主流。
    学好Spring有助于进一步学习Spring Boot和Spring Cloud掌握微服务开发。
  • 课程内容:
    第一部分、Spring IOC工厂
    第二部分、Spring AOP编程
    第三部分、持久层集成
    第三部分、事务处理
    第四部分、MVC框架集成
    第五部分、注解编程
  • 学习建议:
    认真听,记笔记
    多练、多想、多问:怎么用→为什么这样做
    坚持

第一章、Spring引入

1、简介

全称:SpringFramework5.X

  • Spring的历史?
    2002年,Rod Johnson概括了Java企业级应用程序开发的现状的和EJB框架的缺陷,并基于普通Java类和设计模式提出了更加简单的解决方案-interface21——衍生成为轻量级的J2EE开发解决方案Spring,于2004年发布第一个版本。

2、EJB的问题

全称:Enterprise Java Bean

  • 问题1-运行环境苛刻
    免费开源的Tomcat Web服务器只提供Servlet引擎,EJB需要服务器支持EJB容器
    Orcale和IBM提供的支持Servlet和EJB的应用服务器软件( Weblogic、Websphere)收费闭源。不方便中小公司定制使用
  • 问题2-代码移植性差
    EJB代码需要实现不同服务器提供的接口,代码随着需要服务器变化

总结:EJB是重量级的框架

3、什么是Spring?

  • 轻量级
    对运行环境没有额外要求,可运行在提供Servlet引擎的服务器软件上
    不需要实现任何额外接口,代码移植性好
  • Java EE解决方案:
    提供了传统JavaEE分层开发Controller、Service、DAO的一整套解决方案
  • 整合设计模式
    工厂
    代理
    模板
    策略

4、设计模式简介

广义概念:面向对象设计中,解决特定问题的经典代码
侠义概念:GOF4人帮定义的23种设计模式

  • 创建型:单例、原型、工厂、抽象工厂、建造者
  • 结构型:适配器、桥接、组合、装饰者、外观、享元、代理
  • 行为型:责任链、命令、解释器、迭代器、中介者、备忘录、观察者、状态、策略、模板方法、访问者

5、工厂设计模式

概念:通过工厂类创建对象,程序中借助工厂类方法获取对象

好处:解耦合

耦合:代码间的强关联,改变一方影响另一方;不利于代码维护

public class ActionServletController{
	Userservice userService = new UserServiceImp();
	//将接口的实现类硬编码到程序中
	//使用另一种Service时,需要修改Controller代码
}

6、工厂模式编码实现

6-1、工厂类-消除调用对象和被调用对象之间的耦合

  • JavaBean 省略了getter&setter结构
public class User {
    String name;
    String password;
    public User() {
    }
    public User(String name, String password) {
        this.name = name;
        this.password = password;
    }
}
  • 数据库访问对象 DAO
//Dao接口
public interface UserDao {
    void save(User user);
    void queryUserByNameAndPassword(String name,String password);
}
//Dao实现类 :主要体现工厂模式,这里Dao方法实现不具备参考意义
public class UserDaoImp implements UserDao{
    @Override
    public void save(User user) {
        System.out.println("insert into user_t " + user);
    }
    @Override
    public void queryUserByNameAndPassword(String name, String password) {
        System.out.println("queryName = " + name + " queryPassword = " + password);
    }
}
  • 业务对象 Service
//Service接口
public interface UserService {
    void register(User user);
    void login(String name,String password);
}
//Service实现类
public class UserServiceImp implements UserService{
    private UserDao userDao = new UserDaoImp();
    @Override
    public void register(User user) {
        userDao.save(user);
    }
    @Override
    public void login(String name, String password) {
        userDao.queryUserByNameAndPassword(name,password);
    }
}
  • 工厂类
public class BeanFactory1 {
    public static UserService getUserService(){
        return new UserServiceImp();
    }
    public static User getUser(String name,String password){
        return new User(name,password);
    }
}
  • 业务层调用类 使用单元测试类调用【Web中使用Controller类调用】
public class UserTest {
    @Test
    public void test1(){//不使用工厂模式
        UserService userService = new UserServiceImp();

        User tom = new User("tom","123456");
        userService.register(tom);

        userService.login("tom","123456");
    }
    @Test
    public void test2(){//使用工厂模式
        UserService userService = BeanFactory1.getUserService();
        User tom = BeanFactory1.getUser("tom","123456");
        userService.register(tom);
        userService.login("tom","123456");
    }
}

新增了工厂类和被调用对象之间的耦合

6-2、反射-消除工厂类与被调用对象之间的耦合

对象创建方式改变:new关键字+构造器 → 反射机制 + 构造器

import java.lang.reflect.Constructor;
public class BeanFactory2 {
    public static UserService getUserService(){
        //利用反射和无参构造器创建对象
        UserService userService = null;
        try {
            Class clazz = Class.forName("UserServiceImp");
            Constructor constructor = clazz.getConstructor();
            userService = (UserService)constructor.newInstance();
        } catch (Exception e) {//简化了异常处理;实际开发中不建议
            e.printStackTrace();
        }
        return userService;
    }
    public static User getUser(String name,String password){
    	//利用反射和有参构造器创建对象
        User user = null;
        try {
            Class clazz = Class.forName("User");
            Constructor constructor = clazz.getConstructor(String.class, String.class);
            user = (User)constructor.newInstance(name,password);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return user;
    }
}
  • 测试代码
import org.junit.Test;
public class UserTest {
    @Test
    public void useBeanFactory2(){//使用反射工厂
        UserService userService = BeanFactory2.getUserService();
        User tom = BeanFactory2.getUser("tom","123456");
        userService.register(tom);
        userService.login("tom","123456");
    }

新增了工厂类和被调用类之间的耦合

6-3、配置文件-消除工厂类和被调用类之间的耦合

IDEA中文件夹属性:根据颜色区分

  • Source Root:源码目录

  • Resources Root : 源码需要的资源目录(图片配置文件)-作用等同于存放在Source Root目录下

  • Test Source Root:单元测试源码目录

  • Test Resource Root:单元测试需要的资源目录

  • Excluded:不会参与编译的文件目录

  • Generated Sources Root:文件夹中类经常需要重构和快速生成的的文件夹
    【施工中】Spring5
    IDAE中properties配置文件图标
    【施工中】Spring5
    在Sources Root 或 Resource Root文件夹中新建配置文件

# properties文件中,以键值对的方式存储值
# 特殊的map :key 和 value的类型都是String类型
userService=UserServiceImp
# 第一个值是key值,一般设置和类名相关,方便识别
# 第二个值是实现类的全类名(包名+类名【不含后缀】)
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class BeanFactory3 {
    //创建Properties类对象
    private static Properties properties = new Properties();
    //为减少IO读写-使用静态代码块,将配置文件中信息写入Properties集合对象
    static {
        InputStream inputStream=null;
        try {
            //使用系统类加载器获取读取配置文件,生成输入流
            inputStream = ClassLoader.getSystemClassLoader().getResourceAsStream("applicationContext.properties");
            //将输入流中的信息加载到Properties集合对象中
            properties.load(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (inputStream != null) {//关闭输入流
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public UserService getUserService(){
        UserService userService=null;
        try {
        	//通过key值获取实际的value值
            Class clazz = Class.forName(properties.getProperty("userService"));
            userService = (UserService)clazz.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return userService;
    }
}
  • 测试代码
import org.junit.Test;
public class UserTest {
    @Test
    public void useBeanFactory3(){//使用反射加配置文件的工厂
        UserService userService = BeanFactory3.getUserService();
        System.out.println(userService);//多个测试用例代码重复,这里仅表示能获取到对象即可
    }
}

新增了工厂类与key值的强耦合

6-4、将key作为方法参数-消除工厂类与具体的key值的耦合

static Object getBean(String key){
    Object obj = null;
    try {
        Class clazz = Class.forName(key);
        Constructor constructor = clazz.getConstructor();
        obj = constructor.newInstance();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return obj;
}

工厂在获取对象时,只需要将配置文件中的key作为参数传入获取对象的方法

import org.junit.Test;
public class UserTest {
    @Test
    public void useCommonBeanFactory(){//使用通用工厂
        UserService userService =(UserService) CommonBeanFactory.getBean("usrService");
        System.out.println(userService);
    }
}

6-5、工厂模式总结

作用:解决调用对象和被调用对象之间、以及中间层的强耦合。实现在配置文件中新增实现类的key-value,然后就能通过key获取对象使用
使用方式:

  • 第一步、设计类(JavaBean)
  • 第二步、配置文件注册类(key=value)
  • 第三步、通过工厂类方法,传入key获取对象【需要强制类型转换】

7、Spring的本质

Spring 本质是一个工厂 :

  • 工厂类:ApplicationContext类
  • 配置文件:applicationContext.xml

第二章、第一个Spring程序

1、软件版本

  • JDK 8及以上
  • Maven 3.5以上
  • IDEA 2018版本以上
  • Spring版本5.X

2、环境搭建

2-1、Jar包

  • 设置maven pom依赖文件
  • maven中心仓库:https://mvnrepository.com/

2-2、配置文件

@copyright 文章内容来自bilibili UP主 孙帅suns

上一篇:Spring代理模式及AOP


下一篇:SpringIOC和AOP的生活案例