Spring框架入门(一)

Spring概述

  • Spring是什么

    • Spring是分层的Java SE/EE应用full-stack轻量级框架,以IoC(Inverse of Control,反转控制)和AOP(Aspect Oriented Programming,面向切面编程)为内核,提供了展现层Spring MVC和持久层Spring JDBC以及业务层事务管理等众多的企业版应用技术,还能整合开源世界众多著名的第三方框架和类库逐渐成为使用最多的Java EE企业应用开源框架。

  • Spring优势

    • 方便解耦,简化开发

      • 通过Spring提供的IoC容器,可以将对象间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合,用户也不必再为单例模型类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用

    • AOP编程的支持

      • 通过Spring的AOP功能,方便进行面向切面的编程,许多不容易用传统OOP实现的功能可以通过AOP轻松应付

    • 声明式事务的支持

      • 可以将我们从单词烦闷的事务管理代码中解脱出来,通过声明方式灵活的进行事务管理,提高开发效率和质量

    • 方便程序的测试

      • 可以用非容器依赖的编程方式进行几乎所有的测试工作,测试不再是昂贵的操作而是随手可做的事情

    • 方便集成各种优秀框架

      • Spring可以降低各种框架的使用难度,提供了各种优势框架的直接支持

    • 降低JavaEE API的使用难度

      • Spring对JavaEE API(如JDBC)进行了薄薄的封装层,使这些API的使用难度大大降低。

    • Java源码经典学习案例

Spring简单案例降低耦合方式

  • 建立一个高耦合的案例(模拟用户保存)原因:当前类new一个另外的类的对象

    • 用户业务接口代码UserService.java

      package com.mypro.service;
      ​
      /**
       * 用户业务接口
       */
      public interface UserService {
          /**
           * 模拟保存用户
           */
          void saveUser();
      }
    • 用户的业务实现类代码UserServiceImpl.java

      package com.mypro.service.impl;
      ​
      import com.mypro.dao.UserDao;
      import com.mypro.dao.impl.UserDaoImpl;
      import com.mypro.service.UserService;
      ​
      /**
       * 用户的业务实现类
       */
      public class UserServiceImpl implements UserService {
          //高耦合原因之一
          private UserDao userDao = new UserDaoImpl();
      ​
          @Override
          public void saveUser() {
              userDao.saveUser();
          }
      }
    • 用户的持久层接口代码UserDao.java

      package com.mypro.dao;
      ​
      /**
       * 用户的持久层接口
       */
      public interface UserDao {
          /**
           * 模拟保存用户保存的接口
           */
          void saveUser();
      }
    • 用户的持久层实现类代码UserDaoImpl.java

      package com.mypro.dao.impl;
      ​
      import com.mypro.dao.UserDao;
      ​
      /**
       * 用户的持久层实现类
       */
      public class UserDaoImpl implements UserDao {
          @Override
          public void saveUser() {
              System.out.println("用户保存成功!");
          }
      }
    • 主类代码Client.java

      package com.mypro.ui;
      ​
      import com.mypro.service.UserService;
      import com.mypro.service.impl.UserServiceImpl;
      ​
      /**
       * 模拟一个表现层,用于调用业务层
       */
      public class Client {
          public static void main(String[] args) {
              //高耦合原因之二
              UserService userService = new UserServiceImpl();
              userService.saveUser();
          }
      }
  • 第一次优化上述代码,就是将两个出现new对象的耦合原因解决。解决方式如下:

    • 需要一个配置文件来配置我们的service和dao的对象,配置的内容:唯一标识=全限定类名(key=value)

    • 通过读取配置文件中配置的内容,反射创建对象。建议使用properties文件,也可以用xml文件,后者读取比较麻烦。文件名为bean.properties

      userService=com.mypro.service.impl.UserServiceImpl
      userDao=com.mypro.dao.impl.UserDaoImpl
    • 定义一个中间类专门获取properties文件的内容(service和dao的对象)

      package com.mypro.factory;
      ​
      import java.io.InputStream;
      import java.util.Enumeration;
      import java.util.HashMap;
      import java.util.Map;
      import java.util.Properties;
      ​
      /**
       * 一个创建Bean对象的工厂
       */
      public class BeanFactory {
          //定义一个Properties对象
          private static Properties properties;
      ​
          //使用静态代码块为Properties对象赋值
          static{
              try{
                  //实例化对象
                  properties = new Properties();
                  //获取properties文件的流对象
                  InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
                  properties.load(in);
                  }
              }catch(Exception e){
                  throw new ExceptionInInitializerError("初始化properties文件失败!");
              }
          }
      ​
          /**
           * 根据Bean的名称获取bean对象
           * @param beanName
           * @return
           */
          public static Object getBean(String beanName){
              Object bean = null;
              try{
                  String beanPath = properties.getProperty(beanName);
                  //newInstance()   每次都会调用默认构造函数创建对象
                  bean = Class.forName(beanPath).newInstance();
              }catch(Exception e){
                  e.printStackTrace();
              }
              return bean;
          }
      }
    • 修改出现耦合原因的代码

      //ui包下的Client主类
      UserService userService = BeanFactory.getBean("userService");
      //service包下的UserServiceImpl的类
      UserDao userdao = BeanFactory.getBean("userDao");
  • 第二次优化代码:在第一次优化代码的基础上再次优化。原因:第一次的代码是多例模式的工厂模式,因为在BeanFactory类的getBean方法中出现了newInstance()方法,这个方法是每次都会默认调用构造方法,以至于创建的每个对象是不同的。一旦执行多次保存用户的方法,就会浪费空间。解决方式:使用单例模式的工厂模式

    • 只需创建一个用于存放我们要创建的对象的map集合,我们称之为容器。

      package com.mypro.factory;
      ​
      import java.io.InputStream;
      import java.util.Enumeration;
      import java.util.HashMap;
      import java.util.Map;
      import java.util.Properties;
      ​
      /**
       * 一个创建Bean对象的工厂
       *
       * Bean:在计算机英语中,由可重用组件的含义
       * JavaBean:就是创建我们的service和dao的对象
       *  javabean 不等于 实体类,而是远大于的
       *
       *      第一、需要一个配置文件来配置我们的service和dao的
       *           配置的内容:唯一标识=全限定类名(key=value)
       *      第二、通过读取配置文件中配置的内容,反射创建对象
       *           建议使用properties文件,xml文件也可以,不过读取比较麻烦
       */
      public class BeanFactory {
          //定义一个Properties对象
          private static Properties properties;
      ​
          //创建一个用于存放我们要创建的对象的map容器
          private static Map<String, Object> beans;
      ​
          //使用静态代码块为Properties对象赋值
          static{
              try{
                  //实例化对象
                  properties = new Properties();
                  //获取properties文件的流对象
                  InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
                  properties.load(in);
      ​
                  //实例化容器
                  beans = new HashMap<String, Object>();
                  //取出配置文件中所有的key
                  Enumeration keys = properties.keys();
                  //遍历枚举
                  while(keys.hasMoreElements()){
                      //取出每个key
                      String key = keys.nextElement().toString();
                      //根据key获取value
                      String beanPath = properties.getProperty(key);
                      //反射创建对象
                      Object value = Class.forName(beanPath).newInstance();
                      //把key和value存入容器中
                      beans.put(key, value);
                  }
              }catch(Exception e){
                  throw new ExceptionInInitializerError("初始化properties文件失败!");
              }
          }
      ​
          /**
           * 根据Bean的名称获取bean对象
           * @param beanName
           * @return
           */
          public static Object getBean(String beanName){
              bean = beans.get(beanName);
              return bean;
          }
      }
       
posted @ 2020-04-10 14:01  xsha_h  阅读(315)  评论(0编辑  收藏  举报