Spring DI和AOP简介

        Spring可以做很多事情,它为企业级开发提供了丰富的功能,但是这些功能的底层都依赖于它的两个核心特性,也就是依赖注入(dependency injection,DI)面向切面编程(aspect-oriented programming,AOP)。

一、依赖注入

1.构造注入

考虑下面程序展现的Knight类:

package sia.knights;

public class DamselRescuingKnight implements Knight {

  private RescueDamselQuest quest;

  public DamselRescuingKnight() {
    //将DamselRescuingKnightRescueDamselQuest紧耦合
    this.quest = new RescueDamselQuest();
  }

  public void embarkOnQuest() {
    quest.embark();
  }
}

         可以看到,DamselRescuingKnight在它的构造函数中自行创建了RescueDamselQuest。这使得DamselRescuingKnight紧密地和RescueDamselQuest耦合到一起了,因此极大地限制了这个骑士执行探险的能力。如果一个少女需要救援,这个骑士能够召之即来。但是如果一条恶龙需要杀掉,或者让一个圆桌滚起来,那么这个骑士就爱莫能助了。

我们再定义一个Knight类:

package sia.knights;
  
public class BraveKnight implements Knight {

  private Quest quest;

  //通过构造函数将Quest注入进来
  public BraveKnight(Quest quest) {
    this.quest = quest;
  }

  public void embarkOnQuest() {
    quest.embark();
  }
}

        我们可以看到不同于之前的DamselRescuingKnightBraveKnight 没有自行创建探险任务,而是在构造的时候把探险任务作为构造器参数传入。这是依赖注入的方式之一,即构造器注入(constructor injection)

        更重要的是,传入的探险类型是Quest,也就是所有探险任务都必须实现一个接口。所以,BraveKnight 能够响应RescueDamselQuest(少女救援请求)、SlayDragonQuest(屠杀恶龙请求)、MakeRoundTableRounderQuest(圆桌滚起来请求)等任意的Quest实现。

2.完整依赖注入举例

BraveKnight.java:

package sia.knights;
  
public class BraveKnight implements Knight {

  private Quest quest;

  //通过构造函数将Quest注入进来
  public BraveKnight(Quest quest) {
    this.quest = quest;
  }

  public void embarkOnQuest() {
    quest.embark();
  }
}

SlayDragonQuest.java:

package sia.knights;

import java.io.PrintStream;

public class SlayDragonQuest implements Quest {

  private PrintStream stream;

  public SlayDragonQuest(PrintStream stream) {
    this.stream = stream;
  }

  public void embark() {
    stream.println("Embarking on quest to slay the dragon!");
  }
}

knight.xml:





  
  




  



KnightConfig.java:

package sia.knights.config;

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

import sia.knights.BraveKnight;
import sia.knights.Knight;
import sia.knights.Quest;
import sia.knights.SlayDragonQuest;

@Configuration
public class KnightConfig {

  @Bean
  public Knight knight() {
    return new BraveKnight(quest());
  }
  
  @Bean
  public Quest quest() {
    return new SlayDragonQuest(System.out);
  }

}

KnightMain.java:

package sia.knights;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class KnightMain {

  public static void main(String[] args) throws Exception {
    //加载Spring上下文
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("META-INF/spring/knight.xml");
    //获取knight bean
    Knight knight = context.getBean(Knight.class);
    //使用knight
    knight.embarkOnQuest();
    context.close();
  }
}

流程梳理如下图: 

Spring DI和AOP简介_第1张图片

 二、应用切面

你可能感兴趣的:(Spring,spring)