博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring快速入门
阅读量:7200 次
发布时间:2019-06-29

本文共 7516 字,大约阅读时间需要 25 分钟。

spring_icon.jpg

一、概述

Spring是J2EE应用程序框架,是轻量级的IoC(控制反转)和AOP(面向切面)容器框架,主要针对javaBean的生命周期进行管理。使用基本的JavaBean代替了传统的EJB,降低了企业应用开发的复杂性。借助依赖注入、AOP应用、面向接口编程等特性,降低了业务组件之间的耦合度,增强了系统的可扩展性。Spring是非侵入式的,应用中的对象不依赖于Spring的特定类。可以整合和兼容其他框架,让已有的技术和框架更加易用。

二、框架结构

Spring框架是一个分层架构,由七个模块组成。Spring的各模块构建在核心容器之上,核心容器定义了创建、配置和管理bean的方式。

  1. Spring Core

    提供了Spring框架的基本功能。核心容器的主要组件是BeanFactory,是工厂模式的实现。BeanFactory使用IoC将应用程序的配置和依赖性规范与实际的应用程序代码分离。

  2. Spring Context

    是一个配置文件,为Spring框架提供上下文信息。Spring上下文包括各种企业服务,如JNDI、EJB、电子邮件、国际化、校验和调度等。

  3. Spring AOP

    通过配置管理特性,该模块将面向方面的编程功能集成到了Spring框架中。为基于Spring的应用程序中的对象提供了事务管理服务,将声明性事务管理集成到应用程序中。

  4. Spring DAO

    提供了有意义的异常层次结构,可用该结构来管理异常处理和错误信息。异常层次结构简化了错误处理,极大地降低了需要编写的异常代码量。

  5. Spring ORM

    Spring框架插入了若干ORM框架,从而提供了ORM的对象关系工具。所有这些框架都遵从Spring的通用事务和DAO异常层次结构。

  6. Spring Web

    Web上下文模块建立在应用程序上下文模块之上,为基于Web的应用程序提供了上下文。Web模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。

  7. Spring MVC

    SpringMVC框架是一个全功能的构建Web应用程序的MVC实现。

三、核心组件

Spring框架的核心组件主要有三个:Bean组件、Context组件、Core组件。

1、Bean组件

Bean组件在Spring的org.springframework.beans包下,这个包下的所有类主要负责bean的定义、创建、以及对bean的解析。在实际使用中只需要关注bean的创建即可,bean的定义和bean的解析由框架完成。

  • bean的创建使用工厂模式,顶层接口是BeanFactory,最终的实现类是DefaultListableBeanFactory。BeanFactory有三个子接口:ListableBeanFactory、HierarchicalBeanFactory、AutowireCapableBeanFactory。这四个接口共同定义了bean的集合、bean之间的关系、以及bean的行为。
  • bean的定义主要由BeanDefinition描述,描述了配置文件中所定义的<bean>节点中的所有信息。当Spring成功解析节点后,节点信息被转化成BeanDefinition对象,之后所有的操作都是针对该对象。
  • bean的解析主要就是对Spring配置文件的解析。

2、Context组件

Context组件在Spring的org.springframework.context包下,提供一个运行时环境,用以保存各个对象的状态。ApplicationContext是Context的顶级父类,标识了一个应用环境的基本信息。还继承了五个接口,主要扩展Context的功能。

ApplicationContext主要有两个子类:

  • ConfigurableApplicationContext,表示该Context是可修改的,用户在构建Context时可以动态添加或修改已有的配置信息。
  • WebApplicationContext,表示是为web准备的Context,可以直接访问ServletContext。

ApplicationContext必须完成以下几件事:

  • 标识一个应用环境
  • 利用BeanFactory创建Bean对象
  • 保存对象关系表
  • 能够捕获各种事件

3、Core组件

Core组件包含了很多关键类,其中一个重要部分就是定义了资源的访问方式。Resource接口封装了各种可能的资源类型,对使用者屏蔽了文件类型的不同。Resource接口继承了InputStreamSource接口,接口中的getInputStream方法返回InputStream类,所有的资源都可以通过这个类来获取,也屏蔽了资源的提供者。ResourceLoader接口屏蔽了资源的加载者,只需要实现这个接口就可以加载所有类型的资源。Context把资源的加载、解析和描述工作委托给ResourcePatternResolver类来完成,由它整合在一起供其他组件使用。

四、原理

1、IoC

IoC是Spring的核心之一。传统情况下,当一个对象依赖于另一个对象时,需要通过new操作主动创建另一个对象的实例,这样的话,两个对象之间就产生了耦合。通过IoC,一个对象依赖的其他对象会通过被动的方式传递进来,而不是自己创建或查找依赖对象。创建依赖对象实例的工作通常由Spring容器来完成,然后注入给依赖者,所以也被称为DI(依赖注入)。

1.1 IoC容器

BeanFactory是IoC容器的核心接口,负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。XMLBeanFactory实现BeanFactory接口,通过获取xml配置文件数据,组成应用对象及对象间的依赖关系。

  • BeanFactoryPostProcessor,在构建BeanFactory时调用
  • BeanPostProcessor,在构建Bean对象时调用
  • InitializingBean,在Bean实例创建时调用
  • DisposableBean,在Bean实例销毁时调用
  • FactoryBean,用来创建Bean实例的Bean

1.2 注入方法

可以通过三种方法进行注入:set方法、构造函数、接口。

set方法注入

可以为属性提供set方法。在配置文件中添加bean标签,属性class的值为对象实现类的完整路径。添加property标签,属性name的值与对象类中对应的属性名称一致,属性value的值就是给对象类中对应的属性注入的值。

实现类:

public class User {    private String username;    public String getUsername() {        return username;    }    public void setUsername(String username) {        this.username= username;    }}

配置文件:

  
    

也可以为对象提供set方法。在配置文件中添加对引用对象的bean声明,属性ref的值是所要引用的对象。这样,框架就会将引用对象注入到对象类中。

实现类:

public class UserAction {    private UserService userservice;    public void setUserService(UserService userservice) {        this.userservice = userservice;    }}

配置文件:

构造方法注入

直接通过构造函数,将要依赖的属性或对象作为参数传递给构造函数。

实现类:

public class UserAction {    private String username;    public UserAction(String username) {        this.username= username;    }}

配置文件:

接口方法注入

并不常用,所以不做介绍。

1.3 自动装配

修改Spring配置文件中bean标签的autowire属性,可以进行自动装配,简化配置,提高开发效率。自动装配属性有六个值,分别代表不同的含义:

  • byName

    从Spring环境中获取目标对象时,目标对象中的属性会根据名称在整个Spring环境中查找bean标签的id属性值。如果有相同的,则获取这个对象,实现关联。要保证id不能重复。

  • byType

    从Spring环境中获取目标对象时,目标对象中的属性会根据名称在整个Spring环境中查找bean标签的class属性值。如果有相同的,则获取这个对象,实现关联。当存在多个相同类型的bean对象时,会出错。

  • constructor

    使用构造方法完成对象注入,也就是根据构造方法的参数类型进行对象查找,相对于采用byType方式。

  • autodetect

    如果对象没有无参数的构造方法,则自动选择constructor的装配方式进行构造注入;如果对象含有无参数的构造方法,则自动选择byType的装配方式进行set注入。

  • default

    默认采用上一级标签的自动装配的值。

  • no

    不进行自动装配。

2、AOP

AOP是Spring的另一个核心。Spring通过AOP,允许分离应用的业务逻辑与系统级服务(如日志、事务、权限等),从而提高了内聚性。

2.1 AOP与OOP

AOP即面向切面编程,与OOP面向对象编程相辅相成。OOP要求职责分离,不同的类完成不同的功能,降低了代码的复杂度,便于重用。但在职责分离的同时,如果多个类需要进行相同操作时,需要在每个类中都加入这些内容,增加了代码的重复性。如果将这些内容单独封装在一个类中,再通过每个类进行调用,会增加类之间的耦合度。AOP就是在程序运行时,动态地将这些内容切入到类的指定方法、指定位置上。OOP中,基本单元是类;AOP中,基本单元是切面。OOP横向分成各个类,AOP纵向给对象加入特定代码。

2.2 AOP术语

AOP中包含很多术语,理解这些术语才能全面的理解AOP的真正含义。

  • 切面(Aspect),横切面的功能,用于抽象出类或接口

    由Advice和Pointcut组成,既包含了横切面的定义,也包含了切入点的定义。可以使用@Aspect注解实现。

  • 增强(Advice),横切面功能的具体实现,对象的实例

    由Aspect添加到特定Joinpoint的代码,

  • 连接点(Joinpoint),程序运行期间的时间节点

    在Spring AOP中,Joinpoint总是表现为方法执行。

  • 切入点(Pointcut),描述横切面功能应用的限制

    使用Pointcut的目的就是提供一组规则来匹配Joinpoint,只为满足条件的Joinpoint添加Advice代码。

  • 代理(Proxy),织入Advice的结果类

    Spring AOP默认使用JDK动态代理为接口实现代理。如果业务逻辑对象没有实现接口,则使用CGLIB代理。Spring AOP建议基于接口编程,对接口进行AOP,而不是基于类。

  • 目标(Target),业务操作的实际对象,织入Advice的目标对象,也被称为被增强的对象

    因为Spring AOP是通过运行时代理的方式实现Aspect的,所以目标对象总是一个代理对象。一个类被AOP织入Advice后,会产生一个结果类,是包含原类和增强逻辑的代理类。

  • 织入(Weave),将组件应用到业务流程中的过程,将Aspect和其他对象关联并创建目标对象的过程

    Spring采用动态代理织入,而AspectJ则采用编译器和类装载器织入。

2.3 用法

定义Aspect

当使用注解@Aspect标注一个Bean后,Spring框架会自动将其添加到Spring AOP中。要想将对象转换成Bean,还需要使用@Component之类的注解。如果一个类被@Aspect标注,那么这个类就不能成为其他Aspect的目标对象了。

@Component@Aspectpublic class Test{}

声明Pointcut

Pointcut声明由两部分组成:一个pointcut表达式,一个方法签名。使用注解@Pointcut标注pointcut表达式。

@Pointcut("execution(* com.service.UserService.*(..))")private void dataAccessOperation() {}

该声明描述的是:匹配com.service.UserService下的所有方法的执行。

pointcut表达式由指示器和操作参数组成。指示器有以下几种:

  • execution,匹配joinpoint的执行
  • within,匹配特定类下的所有joinpoint的执行
  • this,匹配一个bean,该bean是一个给定类型的实例
  • target,匹配一个目标对象,该对象是一个给定类型的实例
  • bean,匹配指定bean下的所有方法
  • args,匹配参数满足要求的方法
  • @annotation,匹配由指定注解所标注的方法

声明Advice

Advice通常是和Pointcut表达式关联在一起使用的。

@Component@Aspectpublic class BeforeAspectTest {    // 定义一个Pointcut, 使用切点表达式函数来描述对哪些Joinpoint使用advise    @Pointcut("execution(* com.service.UserService.*(..))")    public void dataAccessOperation() {    }}@Component@Aspectpublic class AdviseDefine {    // 定义advise    @Before("com.aspect.PointcutDefine.dataAccessOperation()")    public void doBeforeAccessCheck(JoinPoint joinPoint) {        System.out.println("Before advise, method: " + joinPoint.getSignature().toShortString());    }}

3、注解

注解Annotation是一种类似注释的机制,在代码中添加注解可以在之后的某个时间使用这些信息。Java虚拟机不会对注解进行编译,而是通过反射机制读取注解中的信息。使用注解的主要目的是为了提高开发效率,不需要配置过多的xml文件,不必在配置文件中添加标签。

3.1 使用注解

需要在配置文件中增加命名空间和约束文件:

  

3.2 配置基包

告诉框架哪些类使用注解:

3.3 注解种类

Spring框架自带很多注解。

持久层注解@Repository

@Repositorypublic class UserDao{    // ......}

等同于配置文件中的:

服务层注解@Service

@Service(value="testService")public classTestService {    @Resource //相当于自动装配    private UserDao userDao;       public UserDao getUserDao() {        return userDao;    }    public void setUserDao(UserDao userDao) {        this.userDao = userDao;    }}

等同于配置文件中的:

其中,`@Resource表示对象间的关系,默认采用byName方式进行装配,如果找不到关联对象,则采用byType方式装配。

控制层注解@Controller

@Controller(value="ua")@Scope(value="prototype")public class UserAction {    @Resource    private UserService userService;    public UserService getUserService() {        return userService;    }}

等同于配置文件中的:

Tips:以上三层中的组件关键字都可以使用@Component来代替。

从Spring环境中获取Action对象

ServletContext application =request.getSession().getServletContext();ApplicationContext ac = WebApplicationContextUtils.getWebApplicationContext(application);// 获取控制层对象UserAction useraction = (UserAction)ac.getBean("ua");// 设置编码response.setContentType("text/html;charset=GBK");PrintWriter out = response.getWriter();// 分别打印三个层的对象out.println("Action:" + userAction);out.println("Service:" + userAction.getUserService());out.println("Dao:" + userAction.getUserService().getUserDao());

转载于:https://www.cnblogs.com/gefenghua/p/6417627.html

你可能感兴趣的文章
Linux下的TCP Wrapper机制
查看>>
ngx lua模块之ngx.location.capture子请求学习
查看>>
linux 意外删除与恢复
查看>>
Powershell迁徙域用户的属性值
查看>>
***S 2012 交互式报表 -- 深化式报表
查看>>
笔记本--装不上系统怪问题
查看>>
CronTab 任务周期计划
查看>>
学习虚幻4需要储备的知识(程序入门向)
查看>>
MySQL慢日志监控脚本实例剖析
查看>>
《开源安全运维平台-OSSIM最佳实践》喜获清华、北大、国家图书馆等国内一流大学图书馆收藏...
查看>>
数据仓库入门(实验2)创建数据源视图
查看>>
戴尔“蓝雷”炸响软件定义存储
查看>>
Socket descriptor not found. Hint: the problem...
查看>>
常用集群架构实战练习篇
查看>>
rsync在windows与windows服务器之间的同步设置
查看>>
寄语笑笑
查看>>
我辞去了年收入50万的工作,去做在线教育的老师
查看>>
从“比较两个含有多个不同元素的集合是否相同”引申出的几种算法
查看>>
第七讲 SCCM2012部署Endpoint Protect
查看>>
通过memcached实现领号排队功能及python队列实例
查看>>