一、春天简介
1.Spring简化了Java开发
Spring框架是一个应用框架,一般是半成品。在框架的基础上,我们可以专注于业务逻辑,而不是实现每个项目的架构、基础设施和公共功能组件。所以从架构和模式方面学习Spring框架的结构和原理,对我们在架构和模块层面的理解有很大的帮助。Spring Framework(参考文献1)的目的是简化Java开发。主要手段如下:
(1)架构上的解耦:通过DI(依赖注入)管理类型依赖,通过AOP分离关注点,减少重复代码。
(2)设计中广泛采用了DIP(依赖倒置)和ISP(接口隔离)以及Facade(外观)的原则:提供了简化的调用接口,封装了许多优秀的第三方组件。
(3)在语言层面使用注释:通过配置文件和注释简化应用配置(参考。NET属性)。
2.的体系结构和模块。Spring框架:
Spring框架本身的架构就是典型的松散层。外层可以根据需要引用所有内层,内层不能引用外层。Spring的基本组件如下图所示:
从图中可以看出,初始模块只包含四个组件:core\beans\aop\context。后来又增加了Context-Support [1.2]扩展模块、expression[3.0]扩展模块和Beans-Groovy [4.0]扩展模块。
在上述模块的基础上,Spring内置并封装了许多实用的通用组件。主要组件如图所示:
从图中可以看出,spring-oxm、spring-jdbc和spring-web是很多模块的核心,spring-oxm提供了对象和XML之间的映射支持。
二、基础知识
1.DIP: DIP(依赖倒置原理)是DI(依赖注入)的核心(参考文献2)。
(1)高层模块不要依赖低层模块。两者都应该依靠抽象。
(2)抽象不应该依赖于细节。细节应该依赖于抽象。
用人类的语言来说就是把对具体类的引用转化为对其接口的引用,具体类只指接口(reference==dependency,interface==interface或者抽象类)。事实上,当我们调用一个特定的类时,我们只关心它提供的API,而不关心实现。DIP在设计和重构阶段通过技术手段保证解耦。
2.DI: DI(依赖注入)允许我们管理接口和实现类的映射,对象的创建和生命周期的管理,而不必手工编写工厂代码。
(1)接口注入:你必须实现一个特定的接口,这个接口侵入性很强,现在都没人关心和使用。
(2)构造函数注入:依赖体现在构造函数的参数上。
(3)属性注入:依赖体现在属性上。
在实现过程中,可以将类型注册为自己兼容的类型,这样依赖注入就可以直接替换新的实例化对象,所以理解并使用依赖注入工具比不使用或手写工厂要好。依赖注入工具在实现时肯定会被实现为支持不同配置和不同生命周期的对象工厂。但是,即使没有加入依赖倒置原则限制的API,也不代表我们把它当成new的替代品。就像映射工具在实现过程中可以任意映射一样,它不是用来代替赋值的,而是用来处理有实际对应关系的对象之间的映射,比如领域实体和视图模型。
(1)依赖配置:依赖配置是依赖注入的基础。依赖注入工具都至少支持代码配置和文件配置。在Java中,可以通过注释(中的属性)简化配置。网)。
(2)对象工厂:根据配置返回一个或多个对象。这是核心功能。
(3)生命周期管理:一般至少提供四个层次的支持:作用域、单体、线程和HTTP请求作用域。
大多数依赖注入工具在支持依赖倒置原理的基础上,在技术手段上实现了更多的功能,比如类型的兼容转换、命名依赖、配置时直接导入对象等。
三、Spring依赖注入的要点
比恩是POJO (POCO of。网)春天的时候。
Spring依赖注入的核心
BeanFactory是spring中依赖注入的核心接口,其设计主要采用ISP(接口隔离原理)。通过多级接口继承,既保证了单个接口的内聚性,又保证了整个系统的简洁性。这里我们关注的核心是DefaultListableBeanFactory。
如图,查看XmlBeanFactory代码,可以看到x。
mlBeanFactory只是通过XmlBeanDefinitionReader载入了BeanDefinition配置,XmlBeanDefinitionReader负责将配置解析到BeanDefinition。DefaultListableBeanFactory是真正的实现类,其中定义了类型为Map<String, BeanDefinition>的beanDefinitionMap列表用于存储依赖配置。#p#分页标题#e#2.BeanDefinition:
BeanDefinition定义了配置元数据,无论使用java code、xml、Annotation还是Groovy脚本方式,不同的配置方式通过不同的BeanDefinitionReader解析为BeanDefinition。
3.ApplicationContext
ApplicationContext的核心都是将对象工厂功能委托给BeanFactory的实现类DefaultListableBeanFactory。目前最常用的是基于注解的AnnotationConfigApplicationContext和AnnotationConfigWebApplicationContext。
四、Spring依赖注入快速上手
1.使用Java配置代替xml配置
Java配置的核心是@Configuration和@Bean。定义生命周期使用@Scope,需要引入其他配置文件时使用@Import。
(1)@Configuration:应用了@Configuration注解的POCO成为了配置类。相当于xml配置文件。
(2)@Bean:配置类中应用了@Bean注解的方法成为了配置项。相当于xml中的Bean节点。
package me.test.spring_ioc;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
public class App {
public static void main(String<> args) {
AnnotationConfigApplicationContext container = new AnnotationConfigApplicationContext(AppConfig.class);
String message = container.getBean(IAppService.class).Test();
System.out.println(message);
container.close();
}
}
@Configuration
class AppConfig {
@Bean
public IAppService IAppService() {
return new AppService(new Repository<SimpleEntity>());
}
}
class SimpleEntity {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
interface IAppService {
String Test();
}
interface IRepository<T> {
String Test();
}
class AppService implements IAppService {
private IRepository<SimpleEntity> _repo;
public AppService(IRepository<SimpleEntity> repo) {
_repo = repo;
}
@Override
public String Test() {
return this._repo.Test();
}
}
class Repository<T> implements IRepository<T> {
@Override
public String Test() {
return this.getClass().getName();
}
}
#p#分页标题#e#
如果是Web应用程序,应该使用AnnotationConfigWebApplicationContext,在JSP中可通过WebApplicationContextUtils获取ApplicationContext对象。
<%@page import="swp.IAppService"%>
<%@page import="org.springframework.web.context.WebApplicationContext"%>
<%@page
import=" org.springframework.web.context.support.WebApplicationContextUtils"%>
<html>
<body>
<%
WebApplicationContext context = WebApplicationContextUtils
.getRequiredWebApplicationContext(this.getServletContext());
String message = context.getBean(IAppService.class).print();
out.print(message);
%>
</body>
</html>
2.基于Annotation的自动装配
自动装配主要使用@ComponentScan、@Component和@Autowired。
(1)@ComponentScan:作用在配置类上,启用组件扫描。扫描并注册标注了@Component(@Controller\@Service\@Repository)的类型。@Configuration已经应用了@Component注解。
(2)@Autowired:按类型自动装配。@Autowired和使用@Inject(JSR-330)或@Resource(JSR-250)的效果是类似的。@Autowired和@Inject默认按类型注入,@Resource默认按名称注入。
package me.test.spring_ioc;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
public class App {
public static void main(String<> args) {
AnnotationConfigApplicationContext container = new AnnotationConfigApplicationContext(AppConfig.class);
String message = container.getBean(IAppService.class).Test();
System.out.println(message);
container.close();
}
}
@Configuration
@ComponentScan
class AppConfig {
/*@Bean
public IAppService IAppService() {
return new AppService(new Repository<SimpleEntity>());
}*/
}
class SimpleEntity {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
interface IAppService {
String Test();
}
interface IRepository<T> {
String Test();
}
@Component
class AppService implements IAppService {
private IRepository<SimpleEntity> _repo;
@Autowired
public AppService(IRepository<SimpleEntity> repo) {
_repo = repo;
}
@Override
public String Test() {
return this._repo.Test();
}
}
@Component
class Repository<T> implements IRepository<T> {
@Override
public String Test() {
return this.getClass().getName();
}
}
#p#分页标题#e#
小结:
你至少应该知道的:
(1)BeanFactory和BeanDefinition
(2)DefaultListableBeanFactory和ApplicationContext
(3)AnnotationConfigApplicationContext和AnnotationConfigWebApplicationContext
(4)@Configuraton和@Bean
Spring的依赖注入在配置上是基于对象而不是类型,最先支持的是xml而不是注解,到现在也没有比较方便的代码配置机制。虽然现在已经从xml过渡到了注解方式,但基于对象的基础仍然是影响很多方面的缺点。