初识Spring Framework

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xxgujh/article/details/44100595

最近在工作用到了Spring框架,由于以前没有接触过Spring,就从Spring的官方文档开始学起。在“Quick Start”介绍了一个使用Spring做依赖性注入(dependency injection)的例子,该例子使用Maven或GRADlE进行管理的。作者以前没有接触过这两个项目管理工具,由于时间紧迫,就直接使用了Eclipse编译了这个例子。在Eclipse下的文件结构如下:



(由于没有使用项目管理工具,刚开始只加入了spring-context.jar和spring-core.jar,又根据异常信息导入了commouns-logging.jar、spring-expression.jar和spring-beans.jar。这就是不是项目管理工具的麻烦所在。)

hello/MessageService.java的代码如下:

package hello;

public interface MessageService {
    String getMessage();
}
hello/MessagePrinter.java的代码如下:

package hello;

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

@Component
public class MessagePrinter {

    final private MessageService service;

    @Autowired
    public MessagePrinter(MessageService service) {
        this.service = service;
    }

    public void printMessage() {
        System.out.println(this.service.getMessage());
    }
}

hello/App.java的代码如下:

package hello;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.*;

@Configuration
@ComponentScan
public class App {

    @Bean
    MessageService mockMessageService() {
        return new MessageService() {
            public String getMessage() {
              return "Hello World!";
            }
        };
    }

  public static void main(String[] args) {
      ApplicationContext context = 
          new AnnotationConfigApplicationContext(App.class);
      MessagePrinter printer = context.getBean(MessagePrinter.class);
      printer.printMessage();
  }
}

编译运行该项目,会有以下输出:



“Quick Start”最后总结说这个充分体现了依赖性注入(dependency injection)的概念,至于如何体现的作者尝试做一下解析,权当对Spring Framework的一个初步认识。

项目的入口是App.java的main函数,在这个函数中首先声明了一个ApplicationContext对象context,并向下转型为AnnotationConfigApplicationContext对象。ApplicationContext是对一个应用(Application)提供配置的核心接口,AnnotationConfigApplicationContext是它的一个实现,可用来处理用@Configuration,@Component和JSR-330标注的类。由于App.java使用@Configuration进行了标注,故App.class可以作为AnnotationConfigApplicationContext构造器的的参数。

 MessagePrinter printer = context.getBean(MessagePrinter.class);
这句代码通过context的getBean(Class<T>)方法得到了MessagePrinter的一个实例。为什么呢得到MessagePrinter类的一个实例呢?看getBean(Class<T>)的API解释:

Return the bean instance that uniquely matches the given object type, if any.

(如果给定的对象唯一匹配,就返回一个bean实例。)

 printer.printMessage();
调用MessagePrinter的printMessage()方法,该方法如下实现:

 public void printMessage() {
        System.out.println(this.service.getMessage());
    }
其实是调用了接口MessageService的getMessage()方法,由于App.java中的mockMessageService()方法中的匿名内部类实现了MessageService接口,并在getMessage()方法中返回了“hello,world!”字符串,顾能在结果中输出"hello,world!"。

令人迷惑的是在mockMessageService()方法并没有被显式调用,为何其匿名内部类能被实例化并输出信息呢?原因就在于程序中使用的以下Spring标注。

@Configuration 用于标注一个类,表示bean定义的源文件(source);

@Bean 用于标注一个方法,表示一个方法实例化、配置或初始化一个新的对象(Object),这个对象被Spring的控制反转(IoC)容器管理,相当于Spring <bean />XML配置文件中<bean />元素。(详见官方文档

@ComponentScan  用于标注一个类,表示扫描指定包中的@Component标注的类,并将这些类注册为Spring IoC容器的bean,亦相当于一个<bean />元素;

@Autowired  用于标注setter方法,构造器,包含多个参数的方法,集合等等,用于自动绑定;

@Component  用于标注一个类

由于MessagePrinter中有如下构造器:

  @Autowired
    public MessagePrinter(MessageService service) {
        this.service = service;
    }
从这个构造器中可以到MessagePrinter依赖MessgeServie,并用@Autowired标注。这就表示在通过contexnt.getBean(MessagePrinter.class)得到MessagePrinter的一个实例时,会将对MessageService的依赖自动绑定到MessageService类,将查找所有能作为<bean />元素的类(@Component @Configuration标注)或方法(@Bean标注),而在App.java中有如下方法:

 @Bean
    MessageService mockMessageService() {
        return new MessageService() {
            public String getMessage() {
              return "Hello World!";
            }
        };
    }
查找到这个方法后会将这个MessageService实现注入到MessagePrinter实例中,从而实现“hello,world!”的输出。

以上就是作者对Spring Framework文档“Quick Start”例子的解析,有不当之处=请多多指教。


猜你喜欢

转载自blog.csdn.net/xxgujh/article/details/44100595
今日推荐