前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring学习笔记(一)——Spring介绍及工厂模式解耦

Spring学习笔记(一)——Spring介绍及工厂模式解耦

作者头像
不愿意做鱼的小鲸鱼
发布2022-09-24 09:48:27
2620
发布2022-09-24 09:48:27
举报
文章被收录于专栏:web全栈web全栈

Spring概述

Spring是什么

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

为什么要学习Spring

  1. 方便解耦,简化开发:Spring就是一个大工厂,可以将所有对象的创建和依赖关系交给Spring来管理,避免硬编码所造成的过度程序耦合。
  2. AOP编程的支持:Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能。
  3. 声明式事务的支持:只需要通过配置就可以完成对事务的管理,而无需手动编程
  4. 方便程序的测试:Spring对Junit4支持,可以通过注解方便的测试Spring程序
  5. 方便集成各种优秀框架:Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts、Hibernate、Mybatis、Quartz等)的直接支持
  6. 降低JavaEE API的使用难度:Spring对JavaEE开发中非常难用的一些API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大降低。

spring 的体系结构

在这里插入图片描述
在这里插入图片描述

Spring相关概念

程序的耦合:

耦合:程序间的依赖关系 * 类之间的依赖 * 方法间的依赖

解耦:降低程序间的依赖关系

实际开发中:应该做到编译器不依赖,运行时才依赖。

解耦的思路: 1. 使用反射来创建对象,而避免使用new关键字。 2. 读取配置文件来获取来创建的对象的全限定类名

总结: 耦合是影响软件复杂程度和设计质量的一个重要因素,在设计上我们应采用以下原则:如果模块间必须存在耦合,就尽量使用数据耦合,少用控制耦合,限制公共耦合的范围,尽量避免使用内容耦合。

JavaBean:Java语言中可重复使用的组件

工厂模式和控制反转

工厂模式解耦:在实际开发中我们可以把三层的对象都使用配置文件配置起来,当启动服务器应用加载的时候,让一个类中的方法通过读取配置文件,把这些对象创建出来并存起来。在接下来的使用的时候,直接拿过来用就好了。那么,这个读取配置文件,创建和获取三层对象的类就是工厂。 当某一个接口删除后,编译不会报错,依然可以正常执行,但是会报异常“找不到文件”。

降低依赖关系可以用工厂模式来实现。工厂模式可以手写,但是这样开发效率很低,所以把工厂模式解耦都交给了Spring框架去做。

控制反转 IOC 控制反转把创建的对象的权力交给框架的重要特征,并非面向对象编程的专业术语,它包括依赖注入(DI)和依赖查找(DL) 作用:削减计算机程序的耦合(解除我们代码中的依赖关系)

在这里插入图片描述
在这里插入图片描述

手写工厂模式解耦案例

  1. IAccountDao
代码语言:javascript
复制
package dao;

/**
 * 账户的持久层接口
 */
public interface IAccountDao {

    /**
     * 模拟保存账户
     */
    void saveAccount();
}
  1. IAccountDaoImpl
代码语言:javascript
复制
package dao.impl;
import dao.IAccountDao;
/**
 * 账户的持久层实现类
 */
public class AccountDaoImpl implements IAccountDao {
    public  void saveAccount(){
        System.out.println("保存了账户");
    }
}
  1. BeanFactory(工厂方法)
代码语言:javascript
复制
package factory;

import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * 一个创建Bean对象的工厂
 *
 * Bean:在计算机英语中,有可重用组件的含义。
 * JavaBean:用java语言编写的可重用组件。
 *      javabean >  实体类
 *
 *   它就是创建我们的service和dao对象的。
 *
 *   第一个:需要一个配置文件来配置我们的service和dao
 *           配置的内容:唯一标识=全限定类名(key=value)
 *   第二个:通过读取配置文件中配置的内容,反射创建对象
 *
 *   我的配置文件可以是xml也可以是properties
 */
public class BeanFactory {
    //定义一个Properties对象
    private static Properties props;

    //定义一个Map,用于存放我们要创建的对象。我们把它称之为容器
    private static Map<String,Object> beans;

    //使用静态代码块为Properties对象赋值
    static {
        try {
            //实例化对象
            props = new Properties();
            //获取properties文件的流对象
            InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
            props.load(in);
            //实例化容器
            beans = new HashMap<String,Object>();
            //取出配置文件中所有的Key
            Enumeration keys = props.keys();
            //遍历枚举
            while (keys.hasMoreElements()){
                //取出每个Key
                String key = keys.nextElement().toString();
                //根据key获取value
                String beanPath = props.getProperty(key);
                //反射创建对象
                Object value = Class.forName(beanPath).newInstance();
                //把key和value存入容器中
                beans.put(key,value);
            }
        }catch(Exception e){
            throw new ExceptionInInitializerError("初始化properties失败!");
        }
    }

    /**
     * 根据bean的名称获取对象
     * @param beanName
     * @return
     */
    public static Object getBean(String beanName){
        return beans.get(beanName);
    }

    /**
     * 根据Bean的名称获取bean对象
     * @param beanName
     * @return

    public static Object getBean(String beanName){
        Object bean = null;
        try {
            String beanPath = props.getProperty(beanName);
//            System.out.println(beanPath);
            bean = Class.forName(beanPath).newInstance();//每次都会调用默认构造函数创建对象
        }catch (Exception e){
            e.printStackTrace();
        }
        return bean;
    }*/
}
  1. IAccountService
代码语言:javascript
复制
package service;
/**
 * 账户业务层的接口
 */
public interface IAccountService {

    /**
     * 模拟保存账户
     */
    void saveAccount();
}
  1. AccountServiceImpl
代码语言:javascript
复制
package service.impl;

import dao.IAccountDao;
import factory.BeanFactory;
import service.IAccountService;

/**
 * 账户的业务层实现类
 */
public class AccountServiceImpl implements IAccountService {

//    private IAccountDao accountDao = new AccountDaoImpl();

    private IAccountDao accountDao = (IAccountDao) BeanFactory.getBean("accountDao");

//    private int i = 1;

    public void  saveAccount(){
        int i = 1;
        accountDao.saveAccount();
        System.out.println(i);
        i++;
    }
}
  1. 配置文件 bean.properties
代码语言:javascript
复制
accountService=com.itheima.service.impl.AccountServiceImpl
accountDao=com.itheima.dao.impl.AccountDaoImpl
  1. 测试文件 Client
代码语言:javascript
复制
package ui;

import factory.BeanFactory;
import service.IAccountService;

/**
 * 模拟一个表现层,用于调用业务层
 */
public class Client {
    public static void main(String[] args) {
        //IAccountService as = new AccountServiceImpl();
        for(int i=0;i<5;i++) {
            IAccountService as = (IAccountService) BeanFactory.getBean("accountService");
            System.out.println(as);
            as.saveAccount();
        }
    }
}

运行结果:

Spring学习笔记(一)——Spring介绍及工厂模式解耦-左眼会陪右眼哭の博客
Spring学习笔记(一)——Spring介绍及工厂模式解耦-左眼会陪右眼哭の博客

通过手写工厂模式清楚的展现了上述图中的工厂代理模式,这种模式可以很有效的降低程序之间的依赖关系,sping就是采用了这种模式来达到解耦的效果。

spring 的 IOC 解决程序耦合

准备 spring 的开发包

官网:http://spring.io/ 下载地址: http://repo.springsource.org/libs-release-local/org/springframework/spring

基本概念

ApplicationContext的三个常用实现类: ClassPathXmlApplicationContext:它可以加载类路径下的配置文件,要求配置文件必须在类路径下。不在的话,加载不了。(更常用) FileSystemXmlApplicationContext:它可以加载磁盘任意路径下的配置文件(必须有访问权限)

AnnotationConfigApplicationContext:它是用于读取注解创建容器的。

核心容器的两个接口引发出的问题: ApplicationContext: 单例对象适用 采用此接口 它在构建核心容器时,创建对象采取的策略是采用立即加载的方式。也就是说,只要一读取完配置文件马上就创建配置文件中配置的对象。 BeanFactory: 多例对象使用 它在构建核心容器时,创建对象采取的策略是采用延迟加载的方式。也就是说,什么时候根据id获取对象了,什么时候才真正的创建对象。

在这里插入图片描述
在这里插入图片描述

什么是单例和多例 单例:创建对象时在不同的地方获取的Bean对象是同一个 多例:创建对象时在不同的地方获取的Bean对象是不同的对象

在这里插入图片描述
在这里插入图片描述
创建bean对象的三种方式
代码语言:javascript
复制
<!--创建Bean的三种方式 -->
    <!-- 第一种方式:使用默认构造函数创建。
            在spring的配置文件中使用bean标签,配以id和class属性之后,且没有其他属性和标签时。
            采用的就是默认构造函数创建bean对象,此时如果类中没有默认构造函数,则对象无法创建。
    -->
    <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"></bean>


    <!-- 第二种方式: 使用普通工厂中的方法创建对象(使用某个类中的方法创建对象,并存入spring容器)
    -->
    <bean id="instanceFactory" class="com.itheima.factory.InstanceFactory"></bean>
    <bean id="accountService" factory-bean="instanceFactory" factory-method="getAccountService"></bean>


    <!-- 第三种方式:使用工厂中的静态方法创建对象(使用某个类中的静态方法创建对象,并存入spring容器)
    -->
    <bean id="accountService" class="com.itheima.factory.StaticFactory" factory-method="getAccountService"></bean>
bean的作用范围调整

bean标签的scope属性: 作用:用于指定bean的作用范围 取值: 常用的就是单例的和多例的 * singleton:单例的(默认值) * prototype:多例的 * request:作用于web应用的请求范围 * session:作用于web应用的会话范围 * global-session:作用于集群环境的会话范围(全局会话范围),当不是集群环境时,它就是session <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"scope="singleton" init-method="init" destroy-method="destroy"></bean>

bean对象的生命周期
  1. 单例对象
    • 出生:当容器创建时对象出生
    • 活着:只要容器还在,对象一直活着
    • 死亡:容器销毁,对象消亡
    • 总结:单例对象的生命周期和容器相同
  2. 多例对象
    • 出生:当我们使用对象时spring框架为我们创建
    • 活着:对象只要是在使用过程中就一直活着。
    • 死亡:当对象长时间不用,且没有别的对象引用时,由Java的垃圾回收器回收

基于 XML 的配置IOC 耦合

  1. 导入jar包依赖
代码语言:javascript
复制
 <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>
 </dependencies>
  1. :在类的根路径下创建一个任意名称的 xml 文件(不能是中文)
代码语言:javascript
复制
<?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">

    <!--把对象的创建交给spring来管理-->
    <!-- 配置 service -->
     <bean id="userService" class="service.impl.UserServiceImpl" scope="singleton"
          init-method="init" destroy-method="destroy"></bean>
    <!-- 配置 dao -->
    <bean id="userDao" class="dao.impl.AccountDaoImpl"></bean>
</beans>
  1. 写Service接口,和接口实现类方法 UserService
代码语言:javascript
复制
package service;/*
 *Created by tao on 2020-03-29.
 */

public interface UserService {
    /**
     * 模拟保存账户
     */
    void saveAccount();
}

UserServiceImpl

代码语言:javascript
复制
package service.impl;/*
 *Created by tao on 2020-03-29.
 */

import service.UserService;

public class UserServiceImpl implements UserService {

    public UserServiceImpl() {
        System.out.println("对象创建了");
    }

    public void saveAccount() {
        System.out.println("service中的saveAccount方法执行了。。。");
    }

    public void init() {
        System.out.println("对象初始化了。。。");
    }

    public void destroy() {
        System.out.println("对象销毁了。。。");
    }
}
  1. 测试配置是否成功
代码语言:javascript
复制
package test;/*
 *Created by tao on 2020-03-29.
 */

import org.springframework.context.support.ClassPathXmlApplicationContext;
import service.UserService;

public class Client {
    public static void main(String[] args) {
        //1.获取核心容器对象
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        //2.根据id获取Bean对象
        UserService us1 = (UserService) ac.getBean("userService");
        UserService us2 = (UserService) ac.getBean("userService");
        System.out.println(us1);
        System.out.println(us1 == us2);
        us1.saveAccount();
    }

}

运行结果

Spring学习笔记(一)——Spring介绍及工厂模式解耦-左眼会陪右眼哭の博客
Spring学习笔记(一)——Spring介绍及工厂模式解耦-左眼会陪右眼哭の博客

使用spring框架基于xml配置,很容易的就实现了上述很复杂的工厂模式解耦。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Spring概述
    • Spring是什么
      • 为什么要学习Spring
        • spring 的体系结构
        • Spring相关概念
          • 程序的耦合:
            • 工厂模式和控制反转
              • 手写工厂模式解耦案例
              • spring 的 IOC 解决程序耦合
                • 准备 spring 的开发包
                  • 基本概念
                    • 创建bean对象的三种方式
                    • bean的作用范围调整
                    • bean对象的生命周期
                  • 基于 XML 的配置IOC 耦合
                  相关产品与服务
                  容器服务
                  腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档