spring框架 ioc

今日教学目标:

  • 了解spring框架

  • 理解spring的IOC的容器

  • 能够编写spring入门案例

  • 能够说出spring的bean标签的配置含义

  • 能够理解Bean的实例化方法

  • 能够掌握Bean的属性注入方法

  • 能够理解复杂类型的属性注入

框架

什么是框架:

框架,即framework。其实就是某种企业级应用的半成品,就是一组组件,供你选用完成你自己的系统。简单说就是使用别人搭好的舞台,你来做表演。而且,框架一般是成熟的,不断升级的软件。

框架是对特定应用领域中的应用系统的部分设计和实现的整体结构。

因为软件系统发展到今天已经很复杂了,特别是服务器端软件,涉及到的知识,内容,问题太多。在某些方面使用别人成熟的框架,就相当于让别人帮你完成一些基础工作,你只需要集中精力完成系统的业务逻辑设计。而且框架一般是成熟,稳健的,他可以处理系统很多细节问题,比如,事务处理,安全性,数据流控制等问题。还有框架一般都经过很多人使用,所以结构很好,所以扩展性也很好,而且它是不断升级的,你可以直接享受别人升级代码带来的好处。

框架的作用:

  1. 提高开发效率。
  2. 增强可重用性:不重复造轮子。
  3. 节约维护成本。
  4. 提供编写规范:良好代码质量。
  5. 解耦底层实现原理:降低了开发难度。
  6. 生产力工具:中小企业要生存,我们程序员要吃饭。

学好框架的必要性:

Spring(包括springmvc)和mybatis是企业开发中最基础的两个框架。

从企业角度分析,在实际开发中通常都会采用成熟的框架作为项目某个技术的解决方案,而掌握这些基础框架已经是企业对开发人员的最基本技能要求。

从自身角度分析,我们通过前面对mybatis框架的学习和使用,在实现持久层操作时代码变得精简的同时,开发时间得到了大大的缩短。

框架学习三要素:

  • 导包
  • 配置文件
  • 核心API

缺陷:避免大炮打蚊子

一、Spring简介

官网地址:spring官网

在这里插入图片描述

Spring focuses on the “plumbing” of enterprise applications so that teams can focus on application-level business logic, without unnecessary ties to specific deployment environments.

Spring是实际意义上的Java编程语言中的行业标准,不学他别说找工作,你甚至不能说学过Java。

Spring是一个开源框架

Spring框架使得企业软件开发变得更加简单。

Spring是一个轻量级控制反转(IoC)和面向切面(AOP)的对象容器框架。

本质:可以理解为项目中,对象的管家。Spring就是一个对象的容器(盒子,瓶子)。web容器

在Spring之前,企业级软件开发主要由EJB(Enterprise Java Bean)来完成,但是随着时间流逝EJB逐步被淘汰了,因为它太过于复杂,开发成本过高。替代EJB并提供非常多的Java企业应用功能。

从简单性、松耦合角度、可测试性角度来说,绝大部分Java语言写的应用都可从Spring中受益:

小结:

◆ 设计目的:解决企业应用开发的复杂性

◆ 功能核心:一个控制反转(IoC)和面向切面(AOP)的对象容器。

◆ 使用范围:任何Java应用均可使用Spring

1.1 发展历程

历史沿革:

  • 1997年,IBM提出了EJB(enterprise java bean咖啡豆)的思想
  • 1998年,SUN制定开发标准规范EJB1.0
  • 1999年,EJB1.1发布–企业应用开发萌芽
  • 2001年,EJB2.0发布
  • 2003年,EJB2.1发布
  • 2006年,EJB3.0发布–企业应用生态诞生–蓬勃发展
  • Rod Johnson(Spring之父)
    • Expert One-to-One J2EE Design and Development(2002)
      阐述了J2EE使用EJB开发设计的优点及解决方案
      Expert One-to-One J2EE Development without EJB(2004)
      阐述了J2EE开发不使用EJB的解决方式(Spring雏形)
  • 2017年9月份发布了spring的最新版本spring 5.0通用版(GA)==>微服务阶段

起源:

要谈Spring的历史,就要先谈J2EE。J2EE应用程序的广泛实现是在1999年和2000年开始的,它的出现带来了诸如事务管理之类的核心中间层概念的标准化,但是在实践中并没有获得绝对的成功,因为开发效率,开发难度和实际的性能都令人失望。

曾经使用过EJB开发Java企业级应用的人都知道,学习EJB和应用非常艰苦。EJB要严格地实现各种不同类型的接口,类似的或者重复的代码大量存在。而配置也是复杂和单调。因为学习EJB的高昂代价,和极低的开发效率,极高的资源消耗,都造成了EJB的使用困难,所以Spring框架出现了。而Spring出现的初衷就是为了解决类似的这些问题,使Java企业级应用开发更加容易。

Spring的形成,最初来自Rod Jahnson所著的一本很有影响力的书籍《Expert One-on-One J2EE Design and Development》,就是在这本书中第一次出现了Spring的一些核心思想,该书出版于2002年。另外一本书《Expert One-on-One J2EE Development without EJB》,更进一步阐述了在不使用EJB开发JAVA EE企业级应用的一些设计思想和具体的做法。

热心提示:别去看EJB!那玩意儿现在根本没人用!!!

小结:

  • 听一下即可,无需掌握

1.2 优点

1.简化企业级应用开发:使企业级应用开发变得更简单: 主要是解耦!

通过Spring提供的IoC容器,可以将对象间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合。用户也不必再为单例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用
  1. 简化类间关系:我们面向接口编程,使用接口而不是使用类,大大简化了类与类之间的关系(解耦)

  2. 简化传统配置:提供了一种企业应用程序配置的最好方法

  3. 简化事务:超级简单的事务支持@Transactional

  4. 简化测试:使得应用程序更容易测试

可以用非容器依赖的编程方式进行几乎所有的测试工作,测试不再是昂贵的操作,而是随手可做的事情。
  1. 简化其他框架:不仅让自己简化,还能简化其他框架,这就是其强大的整合能力,非常的方便集成各种优秀框架;这是其设计理念之一,不与参与任何框架竞争!做框架与框架之间的胶水
Spring可以降低各种框架的使用难度,提供了对各种优秀框架(SpringMVC、Mybatis、Struts等)的直接支持。

1.3 主要模块

在这里插入图片描述

  1. 持久层数据访问:Jdbc,对象关系映射ORM,事务,OXM,JMS…
  2. Web层:SpringMVC,Servlet,Portlet,WebSocket…
  3. 核心容器:Beans,Core,Context,SpEL
  4. 测试
  5. 其他

注意:Spring是一个模块化的框架,Spring功能很多很强大,内容太多,但是并不要求所有的功能我们都得用上,我们使用什么模块什么功能引入对应模块即可。

二、Spring入门案例

注意:我们使用的是Spring框架的5.0.7.RELEASE版本,要求JDK必须是8及以上,tomcat版本是8.5及以上。

2.1 目标:

Spring的入门案例,搭建Spring框架环境,使用Spring的容器来创建对象Account

解析:

Spring配置文件,参考官方开发文档。
https://docs.spring.io/spring/docs/5.0.7.RELEASE/spring-framework-reference/core.html#beans-factory-metadata

Spring容器创建对象,使用的也同样是默认构造,类中不写不行,但默认类一般都含有空参数构造!

核心的api,ApplicationContext(对象的容器)

2.2 实现步骤:

  1. 创建Maven工程,导入依赖坐标
  2. 创建Account实体类
  3. 创建beans.xml配置文件,配置配置文件,参考官方文档
    • 通过配置创建对象,同样使用的是构造方法创建
    • 设置属性值
  4. 编写测试类
    1. 加载xml配置文件,创建Spring的ioc容器
    2. 获取容器中的accountService对象

2.3 实现过程:

  1. 创建Maven工程,导入依赖坐标[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传在这里插入图片描述

    <dependencies>
        <!--spring 的ioc容器jar包-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.7.RELEASE</version>
        </dependency>
        <!--单元测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>
    
  2. 创建Account实体类

    public class Account {
        private Integer id;
        private String name;//用户名称
        private Double money;//账户金额
    	//getter setter toString...省略
    }
    
  3. 创建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属性:设置对象在容器中的唯一标识
        class属性:设置对象的全限定名称,用于反射创建对象
        -->
        <bean id="account" class="com.itheima.pojo.Account">
            <!--
            property标签作用:为创建的对象赋值,前提条件对象中必须有该变量setter方法
            name属性:设置成员变量的名称
            value属性:设置成员变量赋的值
            -->
            <property name="id" value="1"/>
            <property name="name" value="特朗普"/>
            <property name="money" value="50000000"/>
        </bean>
    </beans>
    
  4. 编写测试类

    • 加载xml配置文件,创建Spring的ioc容器
    • 获取容器中的accountService对象
    public class HelloWorldTest {
        @Test
        public void test(){
            //通过配置文件来初始化Spring的核心容器
            ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
            //从容器中获取Account对象
            Account account = (Account) ioc.getBean("account");
            System.out.println(account);
        }
    }
    

2.4 小结:

  1. 创建对象始终是Java编程的核心,这里使用的是bean标签来创建:new,反射(Class.forName(“全限定类名”)),bean标签,BeanFactory对象工厂,构建者设计模式(SqlSessionFactoryBuilder)
  2. 对象创建使用的是默认构造,这里不写不行
  3. Spring的核心容器ApplicationContext
  4. 最关键的是applicationContext.xml,可以随意命名,从今天开始,将伴随你开发的始终

三、控制反转IoC的概念和作用

基本概念:

IOC:inverse of control (反转控制/控制反转),我们之前在一个java类中通过new的方式去引入外部资源(其他类等),这叫正向;现在Spring框架帮我们去new,你什么时候需要你去问Spring框架要,这就是反转(创建对象权利的一个反转),我们丧失了一个权利(主动创建对象的权利),但是我们拥有了一个福利(我们不用考虑对象的创建、销毁等问题)。

控制反转==对象控制权交给Spring的对象容器

注意:IOC和AOP不是从Spring开始才有的,在Spring之前更趋向于理论化,在Spring这才发扬光大的。

IoC的主要作用:解决程序耦合,及管理企业应用中的对象

什么是程序的耦合?

耦合性(Coupling),也叫耦合度,是对模块间关联程度的度量。

限定类与类之间的关系(耦合),对象与对象直接的关系(耦合)

代码中的常见耦合:在对象中new对象

高内聚,低耦合

四、Spring 基于XML的IOC详解

4.1 Spring中工厂的类结构图[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传在这里插入图片描述

BeanFactory和ApplicationContext的区别:

BeanFactory 才是 Spring 容器中的顶层接口。ApplicationContext 是它的子接口。

BeanFactory 和 ApplicationContext 的区别:

  • ApplicationContext:立即加载模式,在Spring启动的时候会立即实例化对象,等待使用
  • BeanFactory:使用到对象的时候(getBean等)才去实例化对象(延迟加载模式),不推荐的测试延迟加载
public class TestApplicationContextAndBeanFactory {
    /**
     * 测试顶级接口BeanFactory(过去的用法,现在不用)
     * 测试对象的延迟加载
     */
    @Test
    public void testBeanFactory(){
        // 加载根目录下的配置文件
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        Resource res = resolver.getResource("beans.xml");
        // 创建Bean工厂类 注意 XmlBeanFactory已经过期!
        BeanFactory factory = new XmlBeanFactory(res);
        AccountDao accountDAO = factory.getBean("accountDao", AccountDao.class);
        AccountService accountService = factory.getBean("accountService", AccountService.class);
        System.out.println(accountDAO);
        System.out.println(accountService);
    }
}

4.2 IOC容器,Bean标签详解

4.2.1 Bean标签属性

  • id:标识符
  • class:实例化类的全限定类名,供反射实例化使用
<!--告诉spring框架 帮助我们创建一个 account对象 类告诉它-->
<bean id="account01" class="com.itheima.pojo.Account">
    <property name="id" value="1"></property>
    <property name="name" value="川建国"></property>
    <property name="money" value="10000"></property>
</bean>
 @Test
public void test01() {
    //调用spring核心对象
    ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
    //默认 spring框架帮你创建对象都是单例的java对象
    Account account01 = (Account) context.getBean("account01");
    Account account02 = (Account) context.getBean("account01");
    Account account03 = (Account) context.getBean("account01");
    System.out.println(account01);
    System.out.println(account02);
    System.out.println(account03);
}

4.2.2 Bean标签注入简单属性

4.2.2.1通过property标签注入属性

普通属性

package com.itheima.pojo;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class User {
    private int id;
    private String name;
    private int age;
    private List<String> hobbies1;
    private Set<String> hobbies2;
    private Map<String,String> hobbies3;
    private String[] hobbies4;
	//getter/setter ....
}
<bean id="user01" class="com.itheima.pojo.User">
    <property name="id" value="1"></property>
    <property name="name" value="川建国"></property>
    <property name="age" value="55"></property>
</bean>
@Test
public void test02() {
    //调用spring核心对象
    ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
    //默认 spring框架帮你创建对象都是单例的java对象
    User user = (User) context.getBean("user01");
    System.out.println(user);
}

集合属性

package com.itheima.pojo;

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

public class User {
    private int id;
    private String name;
    private int age;
    private List<String> hobbies1;
    private Set<String> hobbies2;
    private Map<String,String> hobbies3;
    private String[] hobbies4;

	//getter/setter ....
}

 <bean id="user03" class="com.itheima.pojo.User">
        <property name="id" value="1"></property>
        <property name="name" value="小红"></property>
        <property name="age" value="22"></property>
        <!--hobbies1 定义的是list集合 属性值不能直接用 新建 list标签-->
        <property name="hobbies1" >
            <list>
                <value>看电影</value>
                <value>看书</value>
                <value>喝奶茶</value>
            </list>
        </property>
        <!--hobbies2 定义的是set集合 属性值不能直接用 新建 set标签-->
        <property name="hobbies2" >
            <set>
                <value>写代码</value>
                <value>写代码</value>
                <value>聊天</value>
                <value>睡觉觉</value>
            </set>
        </property>
        <!--hobbies4 定义的是array集合 属性值不能直接用 新建 array标签-->
        <property name="hobbies4">
            <array>
                <value>购物</value>
                <value>收快递</value>
                <value>揍男朋友</value>
            </array>
        </property>
        <!--hobbies3 定义的是map集合 属性值不能直接用 新建 map标签-->
        <property name="hobbies3">
            <map>
                <entry key="chou" value="抽烟"/>
                <entry key="he" value="喝酒"/>
                <entry key="tangtou" value="烫头"/>
            </map>
        </property>
    </bean>
/**
 * 练习注入 集合属性
 */
@Test
public void test04() {
    //调用spring核心对象
    ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
    //默认 spring框架帮你创建对象都是单例的java对象
    User user = (User) context.getBean("user03");
    System.out.println(user);
}
4.2.2.2通过命名空间标签注入属性

添加p命名空间

在这里插入图片描述

<!--p命名空间注入 萝卜白菜各有所爱 了解内容-->
    <bean id="user02" class="com.itheima.pojo.User"
    p:id="2" p:name="张三" p:age="18"
    />
/**
 * 测试使用命名空间注入
 */
@Test
public void test03() {
    //调用spring核心对象
    ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
    //默认 spring框架帮你创建对象都是单例的java对象
    User user = (User) context.getBean("user02");
    System.out.println(user);
}
4.2.2.3通过构造函数注入属性
package com.itheima.pojo;


public class Constructor {
    private int id;
    private String name;
    /*自己手动补充一个无参构造*/
    public Constructor() {
    }

    public Constructor(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

<!-- 通过构造函数注入 用的稍微少一些-->
    <bean id="constructor1" class="com.itheima.pojo.Constructor">
        <!--构造函数注入属性-->
        <constructor-arg name="id" value="1"></constructor-arg>
        <constructor-arg name="name" value="测试构造函数注入"></constructor-arg>
    </bean>
/**
 * 测试感受 构造函数注入
 */
@Test
public void test05() {
    //调用spring核心对象
    ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
    //默认 spring框架帮你创建对象都是单例的java对象
    Constructor constructor = (Constructor) context.getBean("constructor1");
    System.out.println(constructor);
}

4.2.2 Bean标签的生命周期方法和单例多例

  • init-method指定初始化时执行的方法
  • destory-method指定销毁时执行的方法
    • 销毁执行方法,scope配置为例子
    • 关闭方法在ApplicationContext接口实现类ClassPathXmlApplicationContext中定义
package com.itheima.pojo;

/**
 * 演示spring框架帮你创建对象生命周期管理和
 */
public class Life {
    private int id;
    private String name;
    public void chusheng(){
        System.out.println("我出生了!!!");
    }
    public void si(){
        System.out.println("我要嗝屁了...");
    }
    //getter/setter
}

  <!--
        测试单例与否的
        scope="singleton" 默认值 不写就是这个
        scope="prototype" 改成多例模式
        注:
            基本很少使用多例模式
    -->
    <bean id="life1" class="com.itheima.pojo.Life" scope="prototype" >
        <property name="id" value="1"></property>
        <property name="name" value="单例还是多例"></property>
    </bean>

    <bean id="life2" class="com.itheima.pojo.Life" init-method="chusheng" destroy-method="si"  >
        <property name="id" value="2"></property>
        <property name="name" value="测试生命周期的"></property>
    </bean>
    <!--
	<bean id="life3" class="com.itheima.pojo.Life" init-method="chusheng" destroy-method="si" scope="prototype"  >
            <property name="id" value="2"></property>
            <property name="name" value="测试生命周期的"></property>
     </bean>
	-->
    /**
     * 测试感受 spring框架创建的对象默认是单例
     */
    @Test
    public void test06() {
        //调用spring核心对象
        ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
        //默认 spring框架帮你创建对象都是单例的java对象
        Life life10 = (Life) context.getBean("life1");
        System.out.println(life10);
        Life life11 = (Life) context.getBean("life1");
        System.out.println(life11);
    }

    /**
     * 测试感受 spring框架创建的感受生命周期管理
     */
    @Test
    public void test07() {
        //调用spring核心对象
        ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");

        Life life2 = (Life) context.getBean("life2");

        System.out.println(life2);

        ((ClassPathXmlApplicationContext) context).close();
        System.out.println(life2);
    }

    /**
     * 测试感受 spring框架创建的感受生命周期管理而且是多例的
     * 多例模式下 管理不了对象的死亡的
     */
    @Test
    public void test08() {
        //调用spring核心对象
        ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");

        Life life2 = (Life) context.getBean("life3");

        System.out.println(life2);

        ((ClassPathXmlApplicationContext) context).close();
    }

五、 Spring依赖注入DI

5.1依赖注入概念

依赖注入: Dependency Injection。 它是 spring 框架核心 ioc 的具体实现。

我们的程序在编写时, 通过ioc控制反转,把对象的创建交给了 spring,但是代码中不可能出现没有依赖的情况。ioc 解耦只是降低他们的依赖关系,但不会消除。

例如:我们的业务层仍会调用持久层的方法。那这种业务层和持久层的依赖关系, 在使用 spring 之后, 就让 spring 来维护了。

简单的说,就是让框架把持久层对象注入业务层,而不用我们自己去创建。

ioc 讲的是控制反转,对象创建和销毁的权利交给了Spring的容器,那么对象中的成员变量需要对象怎么办?DI,这也是控制反转的一种具体实现。

在这里插入图片描述

准备一个新的项目 有账户信息的增删改查

5.2 导入依赖 编写配置文件 创建容器

<!-- 导入spring框架的核心容器的依赖 -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.7.RELEASE</version>
    </dependency>
<?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">

    <!--
        ioc 指的是 让容器帮助我们创建对象

        也有一个名词  DI dependency injection 依赖注入 它只是ioc实现过程一种手段而已

        不仅仅把对象创建交给容器来做
        而且对象与对象之间关系 也交给容器来管理
        可以将另外一个对象 作为属性注入一个对象中

    -->
    <bean id="AccountService" class="com.itheima.service.impl.AccountServiceImpl" >
        <!-- ref 引用别的对象 -->
        <property name="accountDao" ref="accountDao"></property>
    </bean>

    <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl"></bean>


</beans>
package com.itheima;

import static org.junit.Assert.assertTrue;

import com.itheima.dao.AccountDao;
import com.itheima.service.AccountService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;


public class AppTest {
    /**
     * 简单使用容器创建service对象
     */
    @Test
    public void test01() {

        //创建容器对象
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //获取到accountService对象
        AccountService accountService = context.getBean(AccountService.class);
        accountService.findById(1);
    }

    /**
     * 简单使用容器创建dao对象
     */
    @Test
    public void test02() {

        //创建容器对象
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //获取到accountService对象
        AccountDao accountDao = context.getBean(AccountDao.class);
        accountDao.findById(1);
    }

    /**
     * 演示他们有关联关系的
     */
    @Test
    public void test03() {

        //创建容器对象
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //获取到accountService对象
        AccountService accountService = context.getBean(AccountService.class);
        accountService.findById(1);
    }
}

5.3编写完善的增删改查

实体类

package com.itheima.pojo;

/**
 * @author Administrator
 * @TIME 2020/7/4 9:38
 * @description
 */
public class Account {
    private int id;
    private String name;
    private double money;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }
}

dao 和实现类

package com.itheima.dao;

import com.itheima.pojo.Account;

public interface AccountDao {
    void save(Account account);

    Account findById(int id);

    void update(Account account);

    void del(int id);
}

package com.itheima.dao.impl;

import com.itheima.dao.AccountDao;
import com.itheima.pojo.Account;

/**
 * @author Administrator
 * @TIME 2020/7/4 11:27
 * @description
 */
public class AccountDaoImpl implements AccountDao {
    @Override
    public void save(Account account) {
        System.out.println("保存账户信息");
    }

    @Override
    public Account findById(int id) {
        System.out.println("正在根据id查询账户信息");
        return new Account();
    }

    @Override
    public void update(Account account) {
        System.out.println("正在更新账户信息");
    }

    @Override
    public void del(int id) {
        System.out.println("正在根据id删除账户信息");
    }
}

service和实现类

package com.itheima.service;

import com.itheima.pojo.Account;

public interface AccountService {

    void save(Account account);

    Account findById(int id);

    void update(Account account);

    void del(int id);
}

package com.itheima.service.impl;

import com.itheima.dao.AccountDao;
import com.itheima.pojo.Account;
import com.itheima.service.AccountService;

/**
 * @author Administrator
 * @TIME 2020/7/4 11:26
 * @description
 */
public class AccountServiceImpl implements AccountService {
    /*这里面写的是接口 把面向接口糅合进去了*/
    private AccountDao accountDao;

    public AccountDao getAccountDao() {
        return accountDao;
    }

    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    @Override
    public void save(Account account) {
        accountDao.save(account);
    }

    @Override
    public Account findById(int id) {
        return accountDao.findById(id);
}

    @Override
    public void update(Account account) {
        accountDao.update(account);
    }

    @Override
    public void del(int id) {
        accountDao.del(id);
    }
}

六、spring创建对象几种方式

6.1 简单对象创建 底层就是反射

package com.itheima.entity;

/**
 * foobar 模糊不清楚的
 *
 */
public class SimpleObject {
    private String foo;
    private String bar;

    public String getFoo() {
        return foo;
    }

    public void setFoo(String foo) {
        this.foo = foo;
    }

    public String getBar() {
        return bar;
    }

    public void setBar(String bar) {
        this.bar = bar;
    }

    @Override
    public String toString() {
        return "SimpleObject{" +
                "foo='" + foo + '\'' +
                ", bar='" + bar + '\'' +
                '}';
    }
}

<bean id="simpleObject" class="com.itheima.entity.SimpleObject">
    <property name="foo" value="测试属性1"></property>
    <property name="bar" value="测试属性2"></property>
</bean>
/**
     * 简单对象创建
     */
@Test
public void test01() {

    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    Object o = context.getBean("simpleObject");
    System.out.println(o);

}

6.2 复杂对象创建

有些复杂对象的创建

package com.itheima.entity;

/**
 * 需要用的对象 有可能不是简单的可以反射创建成功 创建过程 略微复杂一些
 *  mybatis框架中sqlSessionFactory mapper实现类 等等 很多对象很麻烦
 *
 */
public class ComplexObject {
    private int id;
    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

6.2.1 实例工厂模式
package com.itheima.entity;

/**
 * 自己定义了一对象 就是用来帮助你创建复杂对象的
 */
public class ComplexObjectFactory {
    public ComplexObject xyz(){
        //假设创建过程需要很多步骤
        ComplexObject object = new ComplexObject();
        object.setId(1);
        object.setName("这是使用ComplexObjectFactory创建出来的对象");
        return object;
    }
}

<!--spring容器帮你创建一个用来创建复杂对象 -->
<bean id="complexObjectFactory" class="com.itheima.entity.ComplexObjectFactory" ></bean>

<bean id="complexObject1" class="com.itheima.entity.ComplexObject"  factory-method="xyz" factory-bean="complexObjectFactory"/>

6.2.2 静态工厂模式
package com.itheima.entity;

/**
 * 自己定义了一对象 就是用来帮助你创建复杂对象的
 */
public class ComplexObjectStaticFactory {
    public static ComplexObject abc(){
        //假设创建过程需要很多步骤
        ComplexObject object = new ComplexObject();
        object.setId(1);
        object.setName("这是使用ComplexObjectStaticFactory创建出来的对象");
        return object;
    }
}

<!-- 静态工厂模式 不太推荐这种方式-->
    <!--class指向是静态工具类 不是需要 生产出来是你要的-->
    <bean id="complexObject2" class="com.itheima.entity.ComplexObjectStaticFactory"  factory-method="abc" ></bean>

6.2.3 FactoryBean标准工厂模式
package com.itheima.entity;

import org.springframework.beans.factory.FactoryBean;

/**
 * 老铁们翻译单词 FactoryBean 工厂bean
 *
 * 目标就是为了复杂对象创建
 *
 *
 *
 */
public class MyComplexObjectFactoryBean implements FactoryBean<ComplexObject>{
    @Override
    public ComplexObject getObject() throws Exception {
        //假设创建过程需要很多步骤
        ComplexObject object = new ComplexObject();
        object.setId(1);
        object.setName("这是使用MyComplexObjectFactoryBean创建出来的对象");
        return object;
    }

    /**
     * 声明这个工厂产出来的对象是啥类型
     * @return
     */
    @Override
    public Class<?> getObjectType() {
        return ComplexObject.class;
    }

    /**
     * 是否是单例 工厂生产出来的东西是否是单例
     * @return
     */
    @Override
    public boolean isSingleton() {
        return true;
    }
}

<!--这才是 我们以后要用的-->
    <bean id="complexObject3" class="com.itheima.entity.MyComplexObjectFactoryBean"></bean>

注:

​ 推荐使用标准的factoryBean模式

总结

1.学习spring框架的入门 他就是容器

2.学习如何生产对象

3.如何注入属性

4.如何注入对象 di

5.spring框架 如果遇到复杂对象 使用factoryBean接口的方式

spring创建对象有几种方式?

四种:

​ 简单对象:(掌握)

​ 反射创建而已

​ 复杂对象:

​ 实例工厂模式

​ 静态工厂模式

​ 推荐使用factoryBean实现接口的方式(掌握)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

娃娃 哈哈

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

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

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

打赏作者

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

抵扣说明:

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

余额充值