初识Spring Framework
来源:程序员人生 发布时间:2015-03-13 08:37:56 阅读次数:3258次
最近在工作用到了Spring框架,由于之前没有接触过Spring,就从Spring的官方文档开始学起。在“Quick Start”介绍了1个使用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)的概念,至于如何体现的作者尝试做1下解析,权当对Spring Framework的1个初步认识。
项目的入口是App.java的main函数,在这个函数中首先声明了1个ApplicationContext对象context,并向下转型为AnnotationConfigApplicationContext对象。ApplicationContext是对1个利用(Application)提供配置的核心接口,AnnotationConfigApplicationContext是它的1个实现,可用来处理用@Configuration,@Component和JSR⑶30标注的类。由于App.java使用@Configuration进行了标注,故App.class可以作为AnnotationConfigApplicationContext构造器的的参数。
MessagePrinter printer = context.getBean(MessagePrinter.class);
这句代码通过context的getBean(Class<T>)方法得到了MessagePrinter的1个实例。为何呢得到MessagePrinter类的1个实例呢?看getBean(Class<T>)的API解释:
Return the bean instance that uniquely matches the given object type, if any.
(如果给定的对象唯1匹配,就返回1个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 用于标注1个类,表示bean定义的源文件(source);
@Bean 用于标注1个方法,表示1个方法实例化、配置或初始化1个新的对象(Object),这个对象被Spring的控制反转(IoC)容器管理,相当于Spring <bean />XML配置文件中<bean />元素。(详见官方文档)
@ComponentScan 用于标注1个类,表示扫描指定包中的@Component标注的类,并将这些类注册为Spring IoC容器的bean,亦相当于1个<bean />元素;
@Autowired 用于标注setter方法,构造器,包括多个参数的方法,集合等等,用于自动绑定;
@Component 用于标注1个类
由于MessagePrinter中有以下构造器:
@Autowired
public MessagePrinter(MessageService service) {
this.service = service;
}
从这个构造器中可以到MessagePrinter依赖MessgeServie,并用@Autowired标注。这就表示在通过contexnt.getBean(MessagePrinter.class)得到MessagePrinter的1个实例时,会将对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”例子的解析,有不当的地方=请多多指教。
生活不易,码农辛苦
如果您觉得本网站对您的学习有所帮助,可以手机扫描二维码进行捐赠