Spring初步学习——Spring IOC/DI

   秋招10月底结束后,自己就又恢复之前的堕落了,没有了秋招的那股劲和上进心,最近也开始要毕设了,自己还是一样的渣,决定站起来,马上都快就业的人什么都不会有点说不过去了!站起来,我还能学!于是乎为毕设做点准备,开始着手学习框架,首先让我们从万能的spring开始着手学起。

 

——>spring设计的领域有:

               移动开发、社交API集成、NoSQL数据库、云计算以及大数据都是spring正在涉足和创新的领域

——>spring的常用术语:

               1、框架:是能够完成一定功能的半成品

               2、非侵入式设计:从框架的角度理解,就是无需继承提供的任何类

               3、轻量级和重量级:轻量级相对于重量级而言的,轻量级一般就是非侵入性的、所 依赖的东西非常少、资源占用非常                      少、部署简单等等;即比较容易使用。

               4、JavaBean:符合javaBean规范的类

              5、pojo:(Plain Old Java Object),简单老式java对象

              6、容器:装对象的对象,并且管理对象的生命周期

一、首先我们来了解一下什么是spring?

1、spring是一个轻量级的DI/IOC和AOP容器的开源框架

2、spring提倡以“最少侵入“的方式来管理应用中的代码

3、spring的根本使命:简化java开发

二、让我们对spring的整体框架有个了解:

  • Data Access/Integration层包含:JDBC、ORM、OXM、JMS和Transaction模块
  • Web层包含:Web、Web-Servlet、WebSocket、Web-Porlet模块
  • AOP模块:提供了一个符合AOP联盟标准的面向切面编程的实现
  • Core Container(核心容器) :包含Beans、Core、Context和SpEL模块
  • Test模块:支持使用Junit和TestING对Spring组件进行测试

三、Spring的优势有哪些?

  • 低侵入/低耦合:降低组件之间的耦合度,实现软件各层之间的解耦 
  • 声明式事务管理:基于切面和惯例
  • 方便集成其他框架:如mybatis、Hibernate
  • 降低java开发难度
  • Spring框架包括了J2EE三层的每一层的解决方案(一站式)

 四、Spring能帮我们做什么?

1、能够帮助我们根据配置文件创建及组装对象之间的依赖关系

2、能够帮助我们无耦合的实现日志记录,性能统计,安全控制

3、能非常简单的帮我们管理数据库事务

4、能提供第三方数据访问框架无缝集成,而且自己也提供了一套JDBC访问模块来方便数据库访问

5、提供与第三方Web框架无缝集成,而且自己也提供了一套Spring MVC框架,来方便web层的搭建

6、spring能方便的与java EE(如Java Mail、任务调度)整合,与更多技术整合比如缓存框架

接下来我们步入Spring的正式学习阶段:

Spring IOC和DI简介 

IOC:Inverse of Control,控制反转,就是原来在程序中我们采取手动创建对象,现在是交给Spring来创建对象,我们只需要获取对象,而不过问出处。也就是将对象的控制权交给了Spring框架

Spring IOC容器的设计主要是基于以下两个接口的:

  • BeanFactory
  • ApplicationContext

      ApplicationContext是BeanFactory的子接口之一,BeanFactory是Spring IOC容器所定义的最底层接口,大部分情况下都会使用ApplicationContext作为Spring IOC的容器,接下来我们来看一下BeanFactory的一些常见方法:

1》【getBean】对应了多个方法来获取Spring  IOC容器的Bean

     ①按照类型拿bean:bean =(Bean)factory.getBean(Bean.class);//要求实例唯一,否则无法确定

     ②按照bean的名字拿bean:bean =(Bean)factory.getBean("BeanName");//不太安全,IDE不会检查其安全性

     ③按照bean的名字和类型拿:bean =(Bean)factory.getBean("beanName",Bean.class);//推荐使用

2》 【isSingleton】用于判断是否是单例,如果判断为真,其意思是该Bean在容器中作为唯一一个单例存在的,而【isPrototype】则相反,如果判断为真,意思是当你从容器中获取bean时,容器会为你重新生成一个新的实例

3》【getAliases】方法是获取别名的方法

接下来我们来认识一个 ApplicationContext 的一些常见实现类

1、ClassPathXmlApplicationContext——读取classpath中的资源

ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

2、FileSystemXmlApplicationContext——读取指定路径的资源

ApplicationContext ac = new FileSystemXmlApplicationContext("c:/applicationContext.xml");

3、XmlWebApplicationContext——需要在Web的环境下才可以运行

XmlWebApplicationContext ac  = new XmlWebApplicationContext();//初始化容器

ac.setService(servletContext) ;//需要指定ServletContext对象

ac.setConfigLocation("/WEB-INF/applicationContext.xml");//指定配置文件路径,开头斜线表示web应用的根目录

ac.refresh();//初始化容器

现在,马上,立刻——我们举例实战喽(我采用的是IDEA进行操作),学习一个ApplicationContext的子类ClassPathXmlApplicationContext

1、编写spring框架的首要任务是将需要用到的jar包导入项目,设置依赖

1.1、在Package,【src】->【pojo】下新建一个【Source】类:

package pojo; 

public class Source { 

    private String fruit; // 类型 

    private String sugar; // 糖分描述 

    private String size; // 大小杯 

    /* setter and getter */ 

}

 1.2、再在【src】目录下新建一个【applicationContext.xml】文件,用于配置Spring,通过xml文件配置的方式装配我们的bean

<?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 name="source" class="pojo.Source">
        <property name="fruit" value="橙子"/>
        <property name="sugar" value="多糖"/>
        <property name="size" value="超大杯"/>
    </bean>
</beans>

1.3、再在【test】下新建一个【TestSpring】类:

package test;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import pojo.Source;

public class TestSpring {

    @Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext(
                new String[]{"applicationContext.xml"}
        );

        Source source = (Source) context.getBean("source");
        System.out.println(source.getFruit());
        System.out.println(source.getSugar());
        System.out.println(source.getSize());
    }
}

 1.4、测试运行:即可以正常拿到通过xml配置的bean,Source

运行结果如下:

橙子
多糖
超大杯

Spring IOC的容器的初始化和依赖注入:

Bean的定义和初始化在Spring IOC容器是两大步骤

Bean的定义分为3步:

1、Resource定位,通过xml配置或者注解的方式

2、BeanDefinition的载入,此时还不会创建Bean的实例

3、BeanDefinition的注册,这个过程就是将BeanDefinition的信息发布到Spring IOC容器中

这个时候还只是被定义,没有对应的实例,没有完成依赖注入,此时还不能够完全使用,Spring Bean还有一个配置选项【lazy-init】,其含义就是是否初始化Spring Bean,在没有任何配置的情况下,他的默认值为default,实际值为false,也就是Spring IOC默认会自动初始化Bean。如果将其设置为true,那么只有当我们使用Spring IOC容器的getBean()方法获取它时,才会进行Bean的初始化,完成依赖注入

装配Spring Bean详解

Spring中提供了3中方法进行配置:

  1. 在xml文件中显式配置(最后,简单易懂,当时用第三方类的时候,就只能采取这种方式了)
  2. 在java的接口和类中实现配置(其次采取,避免了xml配置的泛滥,也较为容易)
  3. 隐式Bean、的发现机制和自动装配原则(优先使用,减少程序开发者的决定权,简单而不失灵活)

1》通过XML、配置装配Bean

使用xml装配Bean需要定义对应的XML,这里需要引入对应的XML模式(XSD)文件,这些文件会定义配置Spring Bean的一些元素,当我们在IDEA中创建XML文件时,会有友好的提示

先来一个最简单的装配:

<bean id="c" class="pojo.Category">
    <property name="name" value="测试" />
</bean>
  • 【id 属性是 Spring 能找到当前 Bean 的一个依赖的编号,遵守 XML 语法的 ID 唯一性约束。必须以字母开头,可以使用字母、数字、连字符、下划线、句号、冒号不能以 / 开头
    不过 id 属性不是一个必需的属性name 属性也可以定义 bean 元素的名称,能以逗号或空格隔开起多个别名,并且可以使用很多的特殊字符,比如在 Spring 和 Spring MVC 的整合中,就得使用 name 属性来定义 bean 的名称,并且使用 / 开头。
    注意: 从 Spring 3.1 开始,id 属性也可以是 String 类型了,也就是说 id属性也可以使用 / 开头,而 bean 元素的 id 的唯一性由容器负责检查。
    如果 id 和 name 属性都没有声明的话,那么 Spring 将会采用 “全限定名#{number}” 的格式生成编号。 例如这里,如果没有声明 “id="c"” 的话,那么 Spring 为其生成的编号就是 “pojo.Category#0”,当它第二次声明没有 id属性的 Bean 时,编号就是 “pojo.Category#1”,以此类推。
  • 【class】 属性显然就是一个类的全限定名
  • 【property】元素是定义类的属性,其中的 name 属性定义的是属性的名称,而 value 是它的值。
  • 【ref】属性注入对象,引用自己定义的类对应的bean

当然也可以装配集合,例如:Set,Map,List,Array和Properties等,具体我们举例看一下

package pojo;

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

public class ComplexAssembly {
    
    private Long id;
    private List<String> list;
    private Map<String, String> map;
    private Properties properties;
    private Set<String> set;
    private String[] array;

    /* setter and getter */
}
<bean id="complexAssembly" class="pojo.ComplexAssembly">
    <!-- 装配Long类型的id -->
    <property name="id" value="1"/>
    
    <!-- 装配List类型的list -->
    <property name="list">
        <list>
            <value>value-list-1</value>
            <value>value-list-2</value>
            <value>value-list-3</value>
        </list>
    </property>
    
    <!-- 装配Map类型的map -->
    <property name="map">
        <map>
            <entry key="key1" value="value-key-1"/>
            <entry key="key2" value="value-key-2"/>
            <entry key="key3" value="value-key-2"/>
        </map>
    </property>
    
    <!-- 装配Properties类型的properties -->
    <property name="properties">
        <props>
            <prop key="prop1">value-prop-1</prop>
            <prop key="prop2">value-prop-2</prop>
            <prop key="prop3">value-prop-3</prop>
        </props>
    </property>
    
    <!-- 装配Set类型的set -->
    <property name="set">
        <set>
            <value>value-set-1</value>
            <value>value-set-2</value>
            <value>value-set-3</value>
        </set>
    </property>
    
    <!-- 装配String[]类型的array -->
    <property name="array">
        <array>
            <value>value-array-1</value>
            <value>value-array-2</value>
            <value>value-array-3</value>
        </array>
    </property>
</bean>

总结:

  • List属性为对应的<list>元素进行装配,然后通过多个<value>元素设值
  • Map属性为对应的<map>元素进行装配,然后通过多个<entry>元素设值,只是<entry>包含一个键值对(key-vlue)的设置
  • Properties属性为对应的<properties>元素进行装配,通过多个<properties>元素设指,只是<properties>元素有一个必填的属性【key】,然后可以设置值
  • Set属性对应的<set>元素进行装配,然后通过多个<value>元素设值
  • 对于数组而言,可以使用<array>设置值,然后通过多个<value>元素设置值

命名空间装配

Spring还提供了对应的命名空间的定义,只是在使用命名空间的时候要先引入对应的命名空间和XML模式(XSD)文件

1》【c-命名空间】(是通过构造器参数的方式)

是在Spring3.0中引入的,它在XML中更为简洁的描述构造器参数的方式,要使用它的话,必须在XML的顶部生命其模式

假设现在有这样一个类:

package pojo;

public class Student {

    int id;
    String name;

    public Student(int id, String name) {
        this.id = id;
        this.name = name;
    }
    // setter and getter
}

在c-命名空间和模式声明之后,我们就可以使用他来声明构造器参数了

<!-- 引入 c-命名空间之前 -->
<bean name="student1" class="pojo.Student">
    <constructor-arg name="id" value="1" />
    <constructor-arg name="name" value="学生1"/>
</bean>

<!-- 引入 c-命名空间之后 -->
<bean name="student2" class="pojo.Student"
      c:id="2" c:name="学生2"/>

c-命名空间属性名以 “c:” 开头,也就是命名空间的前缀。接下来就是要装配的构造器参数名,在此之后如果需要注入对象的话则要跟上 -ref(如c:card-ref="idCard1",则对 card 这个构造器参数注入之前配置的名为 idCard1 的 bean)

很显然,使用 c-命名空间属性要比使用 <constructor-arg> 元素精简,并且会直接引用构造器之中参数的名称,这有利于我们使用的安全性。

我们有另外一种替代方式:(索引的方式)

<bean name="student2" class="pojo.Student"
      c:_0="3" c:_1="学生3"/>

2》【p-命名空间】(采用setter的注入方式)

再引入声明之后,我们就可以通过p-命名空间来设置属性(这个例子需要先删除构造函数,不然要配置<constructor-arg>元素)

<!-- 引入p-命名空间之前 -->
<bean name="student1" class="pojo.Student">
    <property name="id" value="1" />
    <property name="name" value="学生1"/>
</bean>

<!-- 引入p-命名空间之后 -->
<bean name="student2" class="pojo.Student" 
      p:id="2" p:name="学生2"/>
<!--如果属性需要注入其他Bean的话,也可以在后面跟上-ref-->
<bean name="student2" class="pojo.Student"
      p:id="2" p:name="学生2" p:cdCard-ref="cdCard1"/>

3》【util-命名空间】

我们来看一下引入前后的变化:

<!-- 引入util-命名空间之前 -->
<property name="list">
    <list>
        <ref bean="bean1"/>
        <ref bean="bean2"/>
    </list>
</property>

<!-- 引入util-命名空间之后 -->
<util:list id="list">
    <ref bean="bean1"/>
    <ref bean="bean2"/>
</util:list>

4》【import】(引入其他配置文件)

<import resource="bean.xml" />

2》通过注解装配Bean

     上面我们学习了通过XML文件的方式来装配Bean,接下来我们来学使用注解(annotation)的方式装配Bean

在Spring中提供了两种方式让Spring IOC容器发现Bean:

  • 组件扫描:通过定义资源的方式,让Spring IOC容器扫描对应的包,从而把bean装配进来
  • 自动装配:通过注解定义,使得一些依赖关系可以通过注解完成

【使用@Component装配Bean】

package pojo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component(value = "student1")
public class Student {

    @Value("1")
    int id;
    @Value("student_name_1")
    String name;

    // getter and setter
}

@Component注解:表示Spring IOC会把这个类扫描成一个bean实例,而其中的value属性代表这个类在Spring中的id

<bean id="student1" class="pojo.Student" />
相当于
@Component("student1"),甚至直接写成@Component,Spring IOC容器默认以类名来命名,作为id,只不过首字母小写

 @Value注解:表示值的注入,和XML中写的value属性是一致的

这个时候我们声明了这个类,但是Spring IOC并不知道有这个Bean,所以我们就可以使用一个StudentConfig类去告诉Spring IOC:

package pojo;//该类和Student类位于同一个包名下
import org.springframework.context.annotation.ComponentScan;

@ComponentScan//代表进行扫描,默认是扫描当前包的路径,扫描所有带有@Component注解的POJO
public class StudentConfig {
}

接下来我们通过Spring IOC容器的实现类——AnnotationConfigApplicationContext去生成IOC容器:

ApplicationContext context = new 
    AnnotationConfigApplicationContext(StudentConfig.class);//使用AnnotationConfigApplicationContext类去初始化Spring IOC容器,他的配置项是StudentConfig类,
Student student = (Student) context.getBean("student1",
    Student.class);
student.printInformation();

【弊端】:

  • 对于@Component注解,他只是扫描所在包的java类,但是更多的时候我们希望的是可以扫描我们指定的类
  • 通过@Value不能够注入对象

关于@Component的两个配置项:basePackages、basePackageClasses,均是为其包和子包进行扫描装配对应配置的Bean

【自动装配——@Autowired】

自动装配技术是一种由Spring自己发现对应的Bean,自动完成装配工作的方式,通过@Autowired,这个时候spring会根据类型去寻找定义的Bean然后将其注入,接下来看实例:

1、在Package【service】下创建一个StudentService接口:

package service;

public interface StudentService {
    public void printStudentInfo();
}

2、为上面的接口创建一个StudentServiceImpl实现类

package service;

import org.springframework.beans.factory.annotation.Autowired;
import pojo.Student;

@Component("studentService")
public class StudentServiceImp implements StudentService {

    @Autowired//表示在Spring IOC定位所有的Bean后,这个字段需要按类型注入,这样IOC容器就会寻找资源,然后注入
    private Student student = null;

     // getter and setter

    public void printStudentInfo() {
        System.out.println("学生的 id 为:" + student.getName());
        System.out.println("学生的 name 为:" + student.getName());
    }
}

3、编写测试类

// 第一步:修改 StudentConfig 类,告诉 Spring IoC 在哪里去扫描它:
package pojo;

import org.springframework.context.annotation.ComponentScan;

@ComponentScan(basePackages = {"pojo", "service"})
public class StudentConfig {
}

// 或者也可以在 XML 文件中声明去哪里做扫描
<context:component-scan base-package="pojo" />
<context:component-scan base-package="service" />

// 第二步:编写测试类:
package test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import pojo.StudentConfig;
import service.StudentService;
import service.StudentServiceImp;

public class TestSpring {

    public static void main(String[] args) {
        // 通过注解的方式初始化 Spring IoC 容器
        ApplicationContext context = new AnnotationConfigApplicationContext(StudentConfig.class);
        StudentService studentService = context.getBean("studentService", StudentServiceImp.class);
        studentService.printStudentInfo();
    }
}

过程:定义Bean——>初始化Bean,扫描——>根据属性需要从Spring IOC容器中搜寻满足要求的Bean——>满足要求则注入

但是自动装配也有一定的歧义,当我们同时有两个实例,那么Spring IOC就会不知所措,该引入哪一个Bean,为了消除歧义,Spring提供了两个注解:

@Primary注解:代表首要的,会优先注入使用该注解的类

@Qualifier注解:指定注入名称Bean的资源

3》【使用@Bean装配Bean】

当引入第三方包的(jar文件),往往没有这些包的资源,就无法通过@Component注解,这时候就需要使用@Bean注解,注解到方法上,使之成为Spring中返回对象为Spring的Bean资源

首先我们在Package【pojo】下新建一个类,用来测试@Bean注解

package pojo;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration//该注解相当于XML文件的根元素,必须要有才能够解析@Bean注解
public class BeanTester {

    @Bean(name = "testBean")
    public String test() {
        String str = "测试@Bean注解";
        return str;
    }
}

然后在测试类中编写代码,从Spring IOC容器中获取这个Bean

// 在 pojo 包下扫描
ApplicationContext context = new AnnotationConfigApplicationContext("pojo");
// 因为这里获取到的 Bean 就是 String 类型所以直接输出
System.out.println(context.getBean("testBean"));

@Bean 的配置项中包含 4 个配置项:

  • name: 是一个字符串数组,允许配置多个 BeanName
  • autowire: 标志是否是一个引用的 Bean 对象,默认值是 Autowire.NO
  • initMethod: 自定义初始化方法
  • destroyMethod: 自定义销毁方法

使用@Bean注解的好处就是能够动态获取一个Bean对象,能够根据环境不同得到不同的Bean对象,或者说将Spring与其他组件分离

【Bean的作用域】

通过这些例子,想必我们已经认识Bean了,那么Bean的作用域范围究竟多大呢?

在默认情况下,Spring IOC容器只会对一个Bean创建实例,但是有时候我们希望可以获取多个实例,这个时候我们就可以通过@Scope注解或者<bean>元素中的scope属性来设置,例如:

// XML 中设置作用域
<bean id="" class="" scope="prototype" />
// 使用注解设置作用域
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

Spring提供了5种作用域,他会根据情况来决定是否生成新的对象:

作用域类别描述
singleton(单例)在Spring IoC容器中仅存在一个Bean实例 (默认的scope)
prototype(多例)每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时 ,相当于执行new XxxBean():不会在容器启动时创建对象
request(请求)用于web开发,将Bean放入request范围 ,request.setAttribute("xxx") , 在同一个request 获得同一个Bean
session(会话)用于web开发,将Bean 放入Session范围,在同一个Session 获得同一个Bean
globalSession(全局会话)一般用于 Porlet 应用环境 , 分布式系统存在全局 session 概念(单点登录),如果不是 porlet 环境,globalSession 等同于 Session

注:在开发中主要使用scope=“singlen”、scope=“prototype“,对于MVC中的Action使用prototype类型,其他使用singleton,Spring容器会管理Action对象的创建,此时把Action的作用域设置为prototype

【Spring表达式语言简要说明】

Spring还提供了更加灵活的·注入方式,那就是Spring表达式,实际上,Spring EL远比以上注入方式要强大,他拥有很多功能

  • 使用Bean的id来引用Bean
  • 调用指定对象的方法和访问对象的属性
  • 进行运算
  • 提供正则表达式进行匹配
  • 集合配置

我们来看一个Spring表达式的例子

package pojo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component("elBean")
public class ElBean {
    // 通过 beanName 获取 bean,然后注入 
    @Value("#{role}")
    private Role role;
    
    // 获取 bean 的属性 id
    @Value("#{role.id}")
    private Long id;
    
    // 调用 bean 的 getNote 方法
    @Value("#{role.getNote().toString()}")
    private String note;
    /* getter and setter */
}

DI:Dependency Injection,依赖注入,指Spring创建对象的过程,将对象依赖属性(简单值,集合,对象)通过配置设值给对象,即通过另外一种方式为对象设置属性

2.1、在Package【pojo】下新建一个【JuiceMaker】类:

package pojo;

public class JuiceMaker {

    // 唯一关联了一个 Source 对象
    private Source source = null;

    /* setter and getter */

    public String makeJuice(){
        String juice = "xxx用户点了一杯" + source.getFruit() + source.getSugar() + source.getSize();
        return juice;
    }
}

 2.2在xml文件中配置JuiceMaker对象,这里我们通过ref来注入另一个对象

<?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 name="source" class="pojo.Source">
        <property name="fruit" value="橙子"/>
        <property name="sugar" value="多糖"/>
        <property name="size" value="超大杯"/>
    </bean>
    <bean name="juickMaker" class="pojo.JuiceMaker">
        <property name="source" ref="source" />
    </bean>
</beans>

 2.3在【TestSpring】中添加如下代码:

package test;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import pojo.JuiceMaker;
import pojo.Source;

public class TestSpring {

    @Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext(
                new String[]{"applicationContext.xml"}
        );

        Source source = (Source) context.getBean("source");
        System.out.println(source.getFruit());
        System.out.println(source.getSugar());
        System.out.println(source.getSize());

        JuiceMaker juiceMaker = (JuiceMaker) context.getBean("juickMaker");
        System.out.println(juiceMaker.makeJuice());
    }
}

2.4运行结果 如下:

橙子
多糖
超大杯
xxx用户点了一杯橙子多糖超大杯

 总结:IOC和DI其实是同一个概念的不同角度的描述,DI相对于IOC而言,

            明确描述了”被注入对象依赖IOC容器,IOC容器配置依赖对象“

IOC如何实现的?

设想一下,我们如果自己来实现这个依赖注入功能,该怎么做?

1、读取标注或者配置文件,看看JuiceMaker依赖的是哪个Source,拿到类名

2、使用反射的API,基于类名实例化对应的对象实例

3、将对象实例,通过构造函数或者setter,传递给JuiceMaker

          可以看出来,IOC其实就是一个工厂模式的升级版。

与传统方式对比:

    我们之前创建对象都是通过new关键字主动创建一个对象,上面我们是通过IOC方式,对象的生命周期由Spring来管理,直接从Spring那里获取一个对象,IOC(控制反转),将控制权转交给Spring

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值