Spring 框架的作用

我们发现Spring可以做很多事情,但是归根结底,支撑Spring的仅仅是少许的理念,所有的理念都可以追溯到Spring的最根本的使命上:简化Java开发。

Spring的目标是致力于全方位的简化Java开发。这势必引出更多的解释,Spring如何简化Java开发的?

为了减低Java的复杂性,Spring采取了以下4中关键策略:

  • 基于POJO的轻量级和最小侵入性编程;
  • 通过依赖注入和面向接口实现松耦合;
  • 基于切面和惯例进行声明式编程;
  • 通过切面和模板减少样板式代码。

几乎Spring所做的任何事情都可以追溯到上述的一条或多条策略。

POJO(Plain Ordinary Java Object)简单的Java对象

Spring的非入侵式就是不强制类实现Spring的任何接口或类,没有任何地方表明它是一个Spring组件。以为着这个类在Spring应用和非Spring应用中都可以发挥同样的作用。Spring赋予POJO魔力的方式之一就是通过DI来装配他们。

依赖注入(Dependency Injection,简称DI)

控制反转(Inversion of Control,缩写为Ioc),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入,还有一种方式叫依赖查找。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体,将其所依赖的对象的引用传递给它。

任何一个有实际意义的应用都会有两个或者更多的类组成,这些类相互之间进行协作来完成特征的业务逻辑。按照传统的做法, 每个对象负责管理与自己相互协作的对象(即它所依赖的对象) 的引用, 这将会导致高度耦合和难以测试的代码。

通过DI,对象的依赖关系将由系统中负责协调各对象的第三方组件在创建对象的时候进行设定。对象无需自行创建或管理它们的依赖关系。依赖关系将被自动注入到需要它们的对象当中去。

如果一个对象只通过接口(而不是具体实现或初始化过程)来表明依赖关系,那么这种依赖就能够在对象本身毫不知情的情况下,用不同的具体实现进行替换。

创建应用组件之间协作的行为通常称为装配(wiring)。Spring有多种装配bean的方式,采用XML是最常见的一种装配方式。

应用切面

DI能够让相互协作的软件组件保持松散耦合,而面向切面编程(aspect-oriented programming, AOP)允许你把遍布应用各处的功能分离出来形成可重用的组件。

面向切面编程往往被定义为促使软件系统实现关注点的分离一项技术。 系统由许多不同的组件组成, 每一个组件各负责一块特定功能。 除了实现自身核心的功能之外, 这些组件还经常承担着额外的职责。 诸如日志、 事务管理和安全这样的系统服务经常融入到自身具有核心业务逻辑的组件中去, 这些系统服务通常被称为横切关注点, 因为它们会跨越系统的多个组件。

在整个系统内, 关注点(例如日志和安全)的调用经常散布到各个模块中, 而这些关注点并不是模块的核心业务

AOP能够使这些服务模块化, 并以声明的方式将它们应用到它们需要影响的组件中去。 所造成的结果就是这些组件会具有更高的内聚性并且会更加关注自身的业务, 完全不需要了解涉及系统服务所带来复杂性。 总之, AOP能够确保POJO的简单性。

如图所示, 我们可以把切面想象为覆盖在很多组件之上的一个外壳。 应用是由那些实现各自业务功能的模块组成的。 借助AOP, 可以使用各种功能层去包裹核心业务层。 这些层以声明的方式灵活地应用到系统中, 你的核心应用甚至根本不知道它们的存在。 这是一个非常强大的理念, 可以将安全、 事务和日志关注点与核心业务逻辑相分离。

利用AOP, 系统范围内的关注点覆盖在它们所影响组件之上。利用AOP可以Spring配置文件中声明日志模块、安全模块必须切入服务功能。

使用了Spring的aop配置命名空间把bean声明为一个切面。 首先, 需要声明为一个bean, 然后在元素中引用该bean。 为了进一步定义切面, 声明(使用) 在被切入的方法执行前调用bean的方法。 这种方式被称为前置通知(before advice)。 同时声明(使用)在被切入的方法执行后调用bean的方法。 这种方式被称为后置通知(after advice)。

  1. 使用@Aspect注解将一个java类定义为切面类;
  2. 使用@Pointcut注解定义一个切入点,这个切入点可以是一个规则,也可以是注解
  3. 根据切入点不同位置切入内容:

      (1)使用@Before在切入点开始处切入内容
      (2)使用@After在切入点结尾处切入内容
      (3)使用@AfterReturning在切入点return内容之后切入内容(可以用来对处理返回值做一些加工处理)
      (4)使用@Around在切入点前后切入内容,并自己控制何时执行切入点自身的内容
      (5)使用@AfterThrowing用来处理当切入内容部分抛出异常之后的处理逻辑
 

/**
 * 日志切面类
 * @author Administrator
 *
 */
@Aspect
@Component
public class WebLogAspect {
 
	private Logger logger = Logger.getLogger(getClass());
	
    @Pointcut("execution(public * org.springboot.hk.controller.*.*(..))")
    public void webLog(){}
    
    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        // 接收到请求,记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
 
        // 记录下请求内容
        logger.info("URL : " + request.getRequestURL().toString());
        logger.info("HTTP_METHOD : " + request.getMethod());
        logger.info("IP : " + request.getRemoteAddr());
        logger.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        logger.info("ARGS : " + Arrays.toString(joinPoint.getArgs()));
 
    }
 
    @AfterReturning(returning = "ret", pointcut = "webLog()")
    public void doAfterReturning(Object ret) throws Throwable {
        // 处理完请求,返回内容
        logger.info("RESPONSE : " + ret);
    }
    
}

使用模板消除样板式代码

你是否写过这样的代码, 当编写的时候总会感觉以前曾经这么写过? 我的朋友, 这不是似曾相识。 这是样板式的代码(boilerplate code) 。 通常为了实现通用的和简单的任务, 你不得不一遍遍地重复编写这样的代码。

遗憾的是, 它们中的很多是因为使用Java API而导致的样板式代码。 样板式代码的一个常见范例是使用JDBC访问数据库查询数据。 举个例子, 如果你曾经用过JDBC, 那么你或许会写出类似下面的代码。

JDBC不是产生样板式代码的唯一场景。 在许多编程场景中往往都会导致类似的样板式代码, JMS、 JNDI和使用REST服务通常也涉及大量的重复代码。

Spring旨在通过模板封装来消除样板式代码。 Spring的JdbcTemplate使得执行数据库操作时, 避免传统的JDBC样板代码成为了可能。

举个例子, 使用Spring的JdbcTemplate(利用了 Java 5特性的JdbcTemplate实现) 重写的getEmployeeById()方法仅仅关注于获取员工数据的核心逻辑, 而不需要迎合JDBC API的需求。 程序清单展示了修订后的getEmployeeById()方法。

以上展示了Spring通过面向POJO编程、 DI、 切面和模板技术来简化Java开发中的复杂性。 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值