欢迎光临
我们一直在努力

Spring框架(第一期):Spring核心之IOC与AOP详解

1_Spring概念介绍_了解

  • 概念

    在这里插入图片描述

    • Spring 是分层的全栈式的轻量级开发框架, 以IOC和AOP为核心, 官网是 https://spring.io

  • Spring版本情况

    在这里插入图片描述

  • Spring优势

    • 1 方便解耦, 简化开发

      • Spring 通过容器, 将对象的创建从代码中剥离出来, 交给 Spring 控制, 避免直接编码造成模块之间的耦合度高, 用户也不必自己编码处理对象的单例和多例控制, 主要关注接口功能即可, 不用关注具体使用哪个实现类和实现细节问题
    • 2 AOP切面编程

      • AOP 切面编程是程序设计的一种概念, Spring 对该概念实现的比较好, 通过切面编程我们可以在不修改原有代码的情况下实现功能的增加, 通常用于 事务控制, 日志记录, 性能检测, 权限控制等等
    • 3 声明式事务

      • 事务的控制可以托管给 Spring, 我们通过注解或者配置文件声明事务的处理方式即可, 不用我们自己去编码处理
    • 4 整合JUNIT, 方便测试

      • spring 整合 JUNIT 单元测试, 对于项目的功能都可以进行轻松快速的测试, 便于我们调试程序
    • 5 方便整合各种优秀的框架

      • SSM > Spring + SpringMVC + MyBatis
      • SSH > Spring + Hibernate + Strust
      • 各种其他框架
    • 6 丰富的功能封装

      • spring 对 JAVAEE(JDBC, JAVAMail,) 都进行了一系列的封装, 简化我们对于API的使用, 提高程序的开发效率
    • 7 规范的源码学习样本

      • spring 的源码设计巧妙, 结构清晰, 大量使用了设计模式, 是 java 代码规范编写的典范, 也是高级程序员面试中经常会问到的源码
  • Spring的体系结构

    在这里插入图片描述

    • 1. Data Access / Integration(数据访问 / 集成)

      • 数据访问 / 集成层包括 JDBC、ORM、OXM、JMS 和 Transactions 模块,具体介绍如下
        • JDBC 模块:提供了一个 JDBC 的抽象层,大幅度减少了在开发过程中对数据库操作的编码
        • ORM 模块:对流行的对象关系映射 API,包括 JPA、JDO、Hibernate 和 iBatis 提供了的集成层
        • OXM 模块:提供了一个支持对象/XML 映射的抽象层实现,如 JAXB、Castor、XMLBeans、JiBX 和 XStream
        • JMS 模块:指 Java 消息服务,包含的功能为生产和消费的信息
        • Transactions 事务模块:支持编程和声明式事务管理实现特殊接口类,并为所有的 POJO
    • 2. Web 模块

      • Spring 的 Web 层包括 Web、Servlet、Struts 和 Portlet 组件,具体介绍如下
        • Web 模块:提供了基本的 Web 开发集成特性,例如多文件上传功能、使用的 Servlet 监听器的 IoC 容器初始化以及 Web 应用上下文
        • Servlet 模块:包括 Spring 模型—视图—控制器(MVC)实现 Web 应用程序
        • Struts 模块:包含支持类内的 Spring 应用程序,集成了经典的 Struts Web 层
        • Portlet 模块:提供了在 Portlet 环境中使用 MV C实现,类似 Web-Servlet 模块的功能
    • 3. Core Container(核心容器)

      • Spring 的核心容器是其他模块建立的基础,由 Beans 模块、Core 核心模块、Context 上下文模块和 Expression Language 表达式语言模块组成,具体介绍如下
        • Beans 模块:提供了 BeanFactory,是工厂模式的经典实现,Spring 将管理对象称为 Bean
        • Core 核心模块:提供了 Spring 框架的基本组成部分,包括 IoC 和 DI 功能
        • Context 上下文模块:建立在核心和 Beans 模块的基础之上,它是访问定义和配置任何对象的媒介。
          • ApplicationContext 接口是上下文模块的焦点
        • Expression Language 模块:是运行时查询和操作对象图的强大的表达式语言
    • 4. 其他模块

      • Spring 的其他模块还有 AOP、Aspects、Instrumentation 以及 Test 模块,具体介绍如下
        • AOP 模块:提供了面向切面编程实现,允许定义方法拦截器和切入点,将代码按照功能进行分离,以降低耦合性
        • Aspects 模块:提供与 AspectJ 的集成,是一个功能强大且成熟的面向切面编程(AOP)框架
        • Instrumentation 模块:提供了类工具的支持和类加载器的实现,可以在特定的应用服务器中使用
        • Test 模块:支持 Spring 组件,使用 JUnit 或 TestNG 框架的测试

2_Spring_IOC概念引入_重要

  • 控制反转

    • 概念

      • 简单的说就是, 创建对象的权利, 或者是控制的位置, 由 JAVA 代码转移到 spring 容器,由 spring 的容器控制对象的创建, 就是控制反转, spring创建对象时, 会读取配置文件中的信息, 然后使用反射给我们创建好对象之后在容器中存储起来, 当我们需要某个对象时, 通过id获取对象即可, 不需要我们自己去 new
        • 一句话: 创建对象交给容器
  • Spring 解耦合的原理

    • 图解

      在这里插入图片描述

    • 创建 maven 项目,设置 maven

      • 先创建一个空项目

        在这里插入图片描述

      • 名字可以是 spring_all

        在这里插入图片描述

      • 在项目下创建模块 名字可以是 spring_test_01

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

      • pom.xml 中导入 spring 依赖

        <dependencies>
        <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>5.3.5</version>
        </dependency>

        <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>5.3.5</version>
        </dependency>

        <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.3.5</version>
        </dependency>

        <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-expression</artifactId>
        <version>5.3.5</version>
        </dependency>
        </dependencies>

    • 四个依赖介绍

      • spring-context 上下文, 容器
      • spring-beans 创建对象
      • spring-core 核心jar
      • spring-expression 表达式jar
    • 但是事实上, 我们导入 spring-context 的时候, 会自动导入其他依赖的 jar, 自动进行了依赖传递, 所以, 导入一个 spring-context 依赖也可以

      在这里插入图片描述

    • 依赖传递关系图如下

      在这里插入图片描述

    • 为了方便测试, 我们导入 Junit 测试依赖

      <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13.1</version>
      <scope>test</scope>
      </dependency>

    • 在项目中定义一个接口和实现类

      • EmpDao接口和实现类

        在这里插入图片描述

        • 接口中定义一个方法并在实现类中实现
      • 接口

      public interface EmpDao {
      int addEmp();
      }

      • 实现类

      public class EmpDaoImp1 implements EmpDao {
      @Override
      public int addEmp() {
      System.out.println("addEmp invoked");
      return 0;
      }
      }

      • 在 spring 配置容器中的对象
        • 创建 spring 配置文件

          在这里插入图片描述

        • 文件名没有明确要求, 暂时可以叫 spring

          在这里插入图片描述

        • 在 spring.xml 中配置一个需要由容器初始化的对象

          在这里插入图片描述

        • 测试通过容器获取对象

          在这里插入图片描述


3_Spring_IOC原理分析_重要

  • IOC底层原理

    在这里插入图片描述

    • 1 XML解析技术读取配置文件

      <bean id="empDao" class="com.xxx.dao.impl.EmpDaoImpl"></bean>

      • 将上面的信息读取进入程序 对象的ID, 一个是对象的类的全路径名
    • 2 反射技术实例化对象, 放到容器中

      • 获得类的字节码
        • Class clazz = Class.forName("com.xxx.dao.impl.EmpDaoImpl")
      • 通过字节码实例化对象
        • Object obj = clazz.newInstance();
      • 将对象放到一个map集合中
        • map.put("empDao", obj);
    • 3 工厂模式返回 Bean 对象 getBean 方法

      public Object getBean(String name){
      Object obj = map.get(name);
      return obj;
      }

  • IOC接口

    • BeanFactory

      • 接口: IOC 容器基本功能接口, 是 spring 内部使用的接口, 我们在处理业务时一般不直接使用该接口
    • ApplicationContext

      • 接口: BeanFactory 的子接口, 提供更多更强大的功能, 研发人员一般使用的接口

        在这里插入图片描述


4_Spring_XML方式实现DI

  • 背景

    • spring中的Bean的管理:

      • Bean(汉译咖啡豆), 又称JAVABean
      • 其实就是 JAVA 程序程序中的一个个对象, 所以 Bean 的管理其实就是 spring 对于 JAVA 程序中的对象的管理
  • 管理的内容是什么

    • 1 对象的创建 IOC

      • IOC 叫做控制反转, 就是 Spring 给我们创建对象, 然后我们直接用, 不用自己NEW, 前面已经解释过
      • IOC 处理的是对象如何创建的问题
    • 2 属性的赋值 DI

      • DI Dependency Injection, 即 “依赖注入” 就是创建属性时给对象属性赋值
      • 对象功能的实现往往要依赖属性的值, 那么给对象属性赋值就可以说成是依赖注入
      • 由于对象属性不仅仅是基本数据类型, 还可能是其他类, 或者引用类型
      • 那么依赖注入将会把更多的对象之间的关系整理到一起, 可以形成一个庞大的依赖关系
      • DI 处理的是对象的属性赋值和互相依赖的关系
  • spring 给我们提供了两种关于 bean 的方式

    • 1 基于XML方式的 Bean 管理

    • 2 基于注解方式的 Bean 管理

    • 创建新的模块并导入以下依赖

      在这里插入图片描述

    • 依赖

      <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.3.5</version>
      </dependency>
      <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13.1</version>
      <scope>test</scope>
      </dependency>

    • 创建 spring 配置文件,一般 spring 的配置文件很多人约定俗称为 application****.xml

      在这里插入图片描述

    • 准备一个要实例化的类

      public class User {
      private Integer userid;
      private String username;
      private String password;

      @Override
      public String toString() {
      return "User{" +
      "userid=" + userid +
      ", username='" + username + '\\'' +
      ", password='" + password + '\\'' +
      '}';
      }

      public User() {
      System.out.println("noArgConstructor");
      }

      public User(Integer userid, String username, String password) {
      System.out.println("allArgConstructor");
      this.userid = userid;
      this.username = username;
      this.password = password;
      }

      public void setUserid(Integer userid) {
      System.out.println("setUserid");
      this.userid = userid;
      }

      public void setUsername(String username) {
      System.out.println("setUsername");
      this.username = username;
      }

      public void setPassword(String password) {
      System.out.println("setpassword");
      this.password = password;
      }
      }

  • IOC 创建对象

    • 通过无参构造方法构造对象

      <bean id="user1" class="com.xxx.bean.User"></bean>

    • <bean> 标签的常见属性

      <bean id="user1" class="com.xxx.bean.User" name="user1" scope="prototype" lazy-init="true"></bean>

    • 解释

      • id 对象的id
      • class 类的全路径名
      • name 和id类似,一般不用
      • scope 控制对象单例多例和使用范围
      • singleton 作用域(scope 默认值), Spring IOC 容器中只会存在一个共享的 bean 实例
      • prototype作用域 部署的bean,每一次获取都会产生一个新的bean实例,相当与一个new的操作
      • request表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP request内有效
      • session作用域 表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP session内有效
      • global session作用域 类似于标准的HTTP Session作用域,不过它仅仅在基于portlet的web应用中才有意义
      • lazy-init 懒加载 调用getBean的时候再去实例化对象
  • DI 给对象属性赋值

    • 1 通过set方法给对象属性赋值

      <!–property 就是在使用set方法实现依赖注入–>
      <bean id="user1" class="com.msb.bean.User">
      <property name="userid" value="1"></property>
      <property name="username" value="张三"></property>
      <property name="password" value="abcdefg"></property>
      </bean>

    • 2 通过有参构造给对象属性赋值

      <!–
      constructor-arg 就是在使用构造方法实现依赖注入
      constructor-arg 的个数必须和某个构造方法的参数个数向对应
      name 指的是参数名
      index 指的是参数的索引
      value 指的是参数值
      –>

      <bean id="user2" class="com.xxx.bean.User">
      <constructor-arg name="userid" value="2"></constructor-arg>
      <constructor-arg name="username" value="小明"></constructor-arg>
      <constructor-arg name="password" value="123456789"></constructor-arg>
      </bean>

      <bean id="user3" class="com.xxx.bean.User">
      <constructor-arg index="0" value="3"></constructor-arg>
      <constructor-arg index="1" value="小黑"></constructor-arg>
      <constructor-arg index="2" value="987654321"></constructor-arg>
      </bean>

    • 3 通过p名称空间和c名称空间给对象属性赋值

      • 添加约束

        <?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"
        xmlns:c="http://www.springframework.org/schema/c"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

      • 配置对象

        <!–p名称空间, 就是对property的简化处理–>
        <bean id="user4" class="com.xxx.bean.User" p:userid="4" p:username="小东" p:password="111111"></bean>

        <!–c名称空间, 就是对constructor-arg的简化–>
        <bean id="user5" class="com.msb.bean.User" c:userid="5" c:username="小西" c:password="222222"></bean>

      • 测试代码

        public class Test1 {
        @Test
        public void testGetBean() {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        User user1 = context.getBean("user1", User.class);
        User user2 = context.getBean("user2", User.class);
        User user3 = context.getBean("user3", User.class);
        User user4 = context.getBean("user4", User.class);
        User user5 = context.getBean("user5", User.class);

        System.out.println(user1);
        System.out.println(user2);
        System.out.println(user3);
        System.out.println(user4);
        System.out.println(user5);
        }
        }

      • 输出结果

        在这里插入图片描述

    • 4 注入空值和特殊符号

      <bean id="user1" class="com.xxx.bean.User">
      <!–null值–>
      <property name="userid">
      <null></null>
      </property>
      <!–特殊符号 转译字符 < &lt; >&gt; & &amp; –>
      <property name="username" value="&amp;xiaoming&lt;&gt;"></property>
      <!– 特殊符号 <![CDATA[内容]]> –>
      <property name="password">
      <value><![CDATA[&<123456>]]></value>
      </property>
      </bean>

    • 5 关于bean引用

      • 实体类

        package com.xxx.bean;

        import java.util.Date;

        public class Mouse {
        private String name;
        private Date birthdate;

        @Override
        public String toString() {
        return "Mouse{" +
        "name='" + name + '\\'' +
        ", birthdate=" + birthdate +
        '}';
        }

        public Mouse() {}

        public Mouse(String name, Date birthdate) {
        this.name = name;
        this.birthdate = birthdate;
        }

        public String getName() {
        return name;
        }

        public void setName(String name) {
        this.name = name;
        }

        public Date getBirthdate() {
        return birthdate;
        }

        public void setBirthdate(Date birthdate) {
        this.birthdate = birthdate;
        }
        }

        package com.xxx.bean;

        public class Cat {
        private String name;
        private Mouse mouse1;

        @Override
        public String toString() {
        return "Cat{" +
        "name='" + name + '\\'' +
        ", mouse1=" + mouse1 +
        '}';
        }

        public Cat() {}

        public Cat(String name, Mouse mouse1) {
        this.name = name;
        this.mouse1 = mouse1;
        }

        public String getName() {
        return name;
        }

        public void setName(String name) {
        this.name = name;
        }

        public Mouse getMouse1() {
        return mouse1;
        }

        public void setMouse1(Mouse mouse1) {
        this.mouse1 = mouse1;
        }
        }

        • xml 配置
          • 代码详情

            <!–告诉容器准备一个Date对象–>
            <bean id="date1" class="java.util.Date"></bean>

            <bean id="mouse1" class="com.xxx.bean.Mouse">
            <property name="name" value="Jerry"></property>
            <!–bean引用引用外部bean–>
            <property name="birthdate" ref="date1"></property>
            </bean>

            <bean id="cat1" class="com.xxx.bean.Cat">
            <property name="name" value="Tom"></property>
            <!–引用内部bean–>
            <property name="mouse1" >
            <bean class="com.xxx.bean.Mouse">
            <property name="name" value="Jerry2"></property>
            <property name="birthdate">
            <bean class="java.util.Date"></bean>
            </property>
            </bean>
            </property>
            </bean>

            <bean id="mouse2" class="com.xxx.bean.Mouse"></bean>
            <bean id="cat2" class="com.xxx.bean.Cat">
            <property name="name" value="Tom2"></property>
            <!–级联引入bean–>
            <property name="mouse1" ref="mouse2"></property>
            <!–用反射调用 get*** 方法,获得对象之后,再赋值–>
            <property name="mouse1.name" value="Jerry3"></property>
            <property name="mouse1.birthdate">
            <bean class="java.util.Date"></bean>
            </property>
            </bean>

    • 6 关于集合注入

      • 实体类

        package com.xxx.bean;

        public class Book {
        private String bname;
        private String author;

        @Override
        public String toString() {
        return "Book{" +
        "bname='" + bname + '\\'' +
        ", author='" + author + '\\'' +
        '}';
        }

        public Book() {}

        public Book(String bname, String author) {
        this.bname = bname;
        this.author = author;
        }

        public String getBname() {
        return bname;
        }

        public void setBname(String bname) {
        this.bname = bname
        }

        public String getAuthor() {
        return author;
        }

        public void setAuthor(String author) {
        this.author = author;
        }
        }

        package com.xxx.bean;

        import java.util.Arrays;
        import java.util.List;
        import java.util.Map;
        import java.util.Set;

        public class Student {
        private String[] books;
        private Set<String> bookSet;
        private List<String> bookList;
        private Map<String,String> bookMap;
        private List<Book> bookList2;

        @Override
        public String toString() {
        return "Student{" +
        "books=" + Arrays.toString(books) +
        ", bookSet=" + bookSet +
        ", bookList=" + bookList +
        ", bookMap=" + bookMap +
        ", bookList2=" + bookList2 +
        '}';
        }

        public String[] getBooks() {
        return books;
        }

        public void setBooks(String[] books) {
        this.books = books;
        }

        public Set<String> getBookSet() {
        return bookSet;
        }

        public void setBookSet(Set<String> bookSet) {
        this.bookSet = bookSet;
        }

        public List<String> getBookList() {
        return bookList;
        }

        public void setBookList(List<String> bookList) {
        this.bookList = bookList;
        }

        public Map<String, String> getBookMap() {
        return bookMap;
        }

        public void setBookMap(Map<String, String> bookMap) {
        this.bookMap = bookMap;
        }

        public List<Book> getBookList2() {
        return bookList2;
        }

        public void setBookList2(List<Book> bookList2) {
        this.bookList2 = bookList2;
        }

        public Student() {}

        public Student(String[] books, Set<String> bookSet, List<String> bookList, Map<String, String> bookMap, List<Book> bookList2) {
        this.books = books;
        this.bookSet = bookSet;
        this.bookList = bookList;
        this.bookMap = bookMap;
        this.bookList2 = bookList2;
        }
        }

        • 配置文件

          <?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"
          xmlns:c="http://www.springframework.org/schema/c"
          xmlns:util="http://www.springframework.org/schema/util"
          xsi:schemaLocation="
          http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans.xsd
          http://www.springframework.org/schema/util
          http://www.springframework.org/schema/util/spring-util.xsd
          "
          >

          <!–定义公共集合–>
          <util:list id="outerbookList">
          <!–声明多个Book对象–>
          <bean id="b1" class="com.xxx.bean.Book" p:bname="JAVA" p:author="马士兵"></bean>
          <bean id="b2" class="com.xxx.bean.Book" p:bname="Go" p:author="马士兵"></bean>
          <bean id="b3" class="com.msb.bean.Book" p:bname="JVM" p:author="马士兵"></bean>
          </util:list>

          <bean id="student1" class="com.xxx.bean.Student">
          <!–数组属性注入–>
          <property name="books">
          <array>
          <value>JAVA</value>
          <value>MySQL</value>
          <value>Spring</value>
          </array>
          </property>

          <!–set集合注入–>
          <property name="bookSet">
          <set>
          <value>JAVA</value>
          <value>MySQL</value>
          <value>Spring</value>
          </set>
          </property>

          <!–list集合注入–>
          <property name="bookList">
          <list>
          <value>JAVA</value>
          <value>MySQL</value>
          <value>Spring</value>
          </list>
          </property>

          <!–map集合注入–>
          <property name="bookMap">
          <map>
          <entry key="JAVA" value="马士兵"></entry>
          <entry key="Go" value="马士兵"></entry>
          <entry key="JVM" value="马士兵"></entry>
          </map>
          </property>

          <!–List对象集合注入–>
          <property name="bookList2" ref="outerbookList"></property>
          </bean>
          </beans>

    • 7 工厂方式获取bean

      • 特点
        • bean 标签中定义的 class 类不是返回的对象的类, 而是生产该对象的工厂
      • 工厂模式
        • GOF 设计模式
      • spring 中给我们定义好了一个工厂接口, 可以生产对象的接口, 我们可以通过工厂来获取 bean
      • 定义工厂对象 实现 FactoryBean 接口

        package com.xxx.bean;

        import org.springframework.beans.factory.FactoryBean;

        public class BookFactory implements FactoryBean<Book> {
        @Override
        public Book getObject() throws Exception {
        Book book = new Book();
        book.setBname("JAVA");
        book.setAuthor("xxx");
        return book;
        }

        @Override
        public Class<?> getObjectType() {
        return null;
        }
        }

      • 配置文件

        <bean id="book" class="com.xxx.bean.BookFactory"></bean>

      • 测试代码

        @Test
        public void testGetBean(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext5.xml");
        Book book = applicationContext.getBean("book", Book.class);
        System.out.println(book);
        }


赞(0)
未经允许不得转载:171主机测评 » Spring框架(第一期):Spring核心之IOC与AOP详解
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址