spring中的两大核心模块:IOC和AOP

Spring就像一个管家,帮你管理事务。传统的应用,应用层(Struts2)和事务层(Service)联系很紧密,通过Spring管理之间的关系,减低其耦合性。Spring的出现就是为了解决现有问题,使开发更快捷,更健壮。另外,一定要好好学习Spring,他可是有一统天下的野心。有针对Struts2的SpringMVC,有针对Hibernate/mybatis的SpringData,以及为了简化开发的 Spring boot 和 Spring Cloud。

第一章:控制反转和容器

IOC:Inversion of Control

DI:Dependency Injection

EJB:Enterprise JavaBeans

服务定位器:Service Locator

IoC的设计原则被许多容器用来解耦组件之间的依赖关系,spring framework提供了一个强大、可扩展的IoC容器来管理组件。

传统:在提到Java EE平台的组件时,会想到EJB。EJB规范明确的定义了EJB组件和EJB容器之间的契约。优点:只要运行在EJB容器里,EJB组件就能获得生命周期的管理、事务管理以及安全服务等诸多好处;缺点:组件不能脱离EJB容器运行,解耦组件之间的依赖很难,太复杂,被称为重量级组件

现在:IoC是轻量级组件,而且被证明很有效。

IoC是一个通用的设计原则,DI则是具体的设计模式,DI是IOC最典型的事务实现,IOC和DI两术语之间会混用。

 

下面三条可以简单的说明IoC的底层实现:

1.1使用容器管理组件

问题:面向对象基本思想是将系统分解成一组可重用的对象。如果没有一个核心模块来管理这些对象,它们将不得不各自创建和管理自己的依赖,结果就是这些对象会紧紧地耦合在一起。

方案:需要一个容器来管理组成系统的对象。该容器集中创建对象,并以注册表的形式提供对象的查找服务;同时,该容器还要管理对象的生命周期,并为这些对象提供一个服务平台。运行于容器里的对象被称为组件,它们必须要遵循容器所定义的规范。一个功能齐全的容器会很复杂。

实现:

1.2使用服务定位器降低查找组件的复杂性

问题:在容器的管理下,组件之间的依赖仅仅是接口依赖,而不是实现依赖。然而,它们还是要用复杂的私有代码从容器里查找自己所需要的组件。

方案:要降低查找组件的复杂性,可以使用Sun的Java EE核心模式——服务定位器。这个模式的思想是,尽量使用服务定位器来封装复杂的查找逻辑,同时对外公开简单的查找方法,然后所有组件都可以将查找请求委派给该服务定位器。

1.3应用控制反转和依赖注入

问题:当组件需要外部资源(数据源或对其他组件的引用)时,最直接也最明智的方法是执行查找,这里成为主动查找。尽管使用了服务定位器来封装查找逻辑,这种查找依旧存在缺点——组件需要知道如何获取资源。

方案:应用IoC,它的思想是反转资源获取的方向:传统的资源查找方式要求组件自己想容器发出请求来查找资源,容器再适时地返回资源(主动查找);应用IoC后,容器主动地将资源推送到它所管理的组件里,组件所要做的仅仅是选择一种合适的方式来接收资源(被动查找)。在DI模式里,容器以一些预先定义好的方式(如通过setter方法)将匹配的资源注入到每个组件里。

IOC原则类似于好莱坞那句低声下气的广告语——“你别来找我,我会去找你的”(Don’t call us,we’ll call you),所以在程序设计模式中,IoC原则也被称为“好莱坞原则”。

1.4主要有三种依赖注入(DI):

1、接口注入(Type 1 IoC)☆

   所有组件必须要实现特定的接口,接口特定于容器,导致组件对容器产生依赖(不用)

2、setter注入(Type 2 IoC)☆☆☆ 

在每个组件实例化之后,容器调用组件的setter方法注入依赖

ReportService reportService = new ReportService();

reportService.setReportGenerator(reportGenerator);

       此种很流行,大多数Java IDE都支持setter方法的自动生成。

缺点:使用者忘记注入依赖,导致NullPointException异常,Spring IoC容器这种高级的会提供检查;第一次注入后,可能会再次调用setter导致再次注入,这种无意修改会产生无法预料的后果。

3、构造器注入(Type 3 IoC)☆☆

       解决了setter注入的两大缺点,但它没有含义明确的方法名,有时候必须参考相关javadoc,降低了代码可读性。

每个组件实例化的时候,容器将依赖作为构造器的参数传入组件的构造器。

在容器中,要显示的创建一个默认的构造器。

ReportService reportService = new ReportService(reportGenerator);

1.5使用配置文件配置容器

问题:为了让容器能够管理组件以及组件之间的依赖,前期必须以正确的信息配置容器。但如果使用Java代码配置则每次修改配置之后都必须重新编译源代码(效率极低)!

方案:使用基于文本的、可读性强的配置文件。属性文件或者XML文件,它们不需要重新编译,如果要经常去改动配置,他们更有效。

XML比较强大,简单容器属性文件就可以了。要将先前的编程配置改为基于属性的配置,需要创建components.properties文件,其中:

新组件定义:使用组件名字作为键,全限定类名作为值。

依赖注入:结合组件名和属性名,中间是“.”,构成键;(在组建类里必须为这个属性定义setter方法),值是另外被注入的组件的引用名。

 

2、Spring简介=Spring Framework概要介绍

 

Spring采用分级方式,在架构上划分为多个模块,我们主要学习模块的功能。

Spring不仅是一个涉及内容广泛的Java/Java EE应用程序框架,也是一个平台,拥有许多与之相关的开源项目---->Spring Portfolio项目。

使用spring framework开发java/java ee应用程序。

a.Spring Framework的安装,了解spring的安装目录结构,及目录下的具体内容;

b.Spring项目Spring IDE是一个Eclipse插件,简化spring应用程序的开发。

2.1 Spring Framework的核心是轻量级的IoC容器,能为简单的Java对象增加企业及服务;

   Spring通过AOP这种优秀的编程方式,为它的组件提供企业及服务;

   Spring IoC容器的作用范围里,组件也称为Bean

 

2.2 可以通过安装spring portfolio项目Spring IDE来开发spring项目(应用程序)。

 

 

3.Spring IoC中基本组件(bean)配置

POJO:Plain Old Java Object 普通的Java对象/JavaBeans

 

Spring里组件也被称为Bean,可以是任意的POJO。

POJO可以用来作为支持业务逻辑的协助类;可理解为简单的实体类,方便程序员使用数据库中的数据表;POJO对象有时也被称为Data对象,在Hibernate/MyBatis框架中,使用对象和数据库中的表对应,对象的属性与表中的字段对应。

 

 

3.1spring IoC中配置Bean

问题:

Spring提供了强大的IoC容器来管理来管理组成应用程序的Bean。要利用容器提供服务,就必须配置Bean,让Bean运行在Spring IoC容器里。

方案:Spring IoC中可通过XML文件、属性文件甚至API来配置Bean。XML文件比较简单成熟。Spring允许使用一个或多个Bean配置文件来配置Bean。

 

3.2实例化spring IoC容器

问题:

在spring IoC容器读取Bean配置创建Bean实例之前,必须对它进行实例化。只有在容器实例化之后,才可以从IoC容器里获取Bean实例并使用它们。

方案:spring提供两种类型的IoC容器实现:Bean Factory(基础实现)、Application Context(高级实现)。后者是对前者的扩展,而且Bean配置文件是相同的。Bean Factory的接口BeanFactory是Application Context接口ApplicationContext的父接口。

 

 

 

Spring AOP使用代理设计模式来作为底层实现原理

5动态代理和经典的Spring AOP

AOP:aspect-orient programming 面向切面编程

GoF:Gang of Four 设计模式

OOP:object-orient programming 面向对象编程

crosscutting concern:横切关注点,跨越应用程序多个模块的功能和需求,企业应用:日志、验证和事务管理。

 

AOP是一种新的方法论,它是对传统的OOP的补充。AOP和OOP经常一起使用。

 

在OOP世界里,应用程序通过类和接口组织

——优点:这些编程元素非常适合实现核心的业务需求;缺点:对于横切关注点不行,横切关注点在企业应用程序里非常普遍。

AOP世界里,为开发者提供了另一种组织应用程序结构的方式。不再是OOP里的类和接口,而是切面这种编程元素。

 

横切关注点的模块化很难通过传统的面向对象的方式模块化:

类比:AOP切面模块化横切关注点,OOP类模块化状态和行为。

 

三种主流的开源AOP框架:AspectJ、JBoss AOP、Spring AOP

AspectJ是Java社区最完整最流行的AOP框架;Spring AOP也比较完整,主要目的给Spring IoC容器提供一种一致性集成的AOP解决方案,它只能处理声明在IoC容器里的Bean的横切关注点。

 

AOP的核心实现技术是:动态代理。

 

5.1非模块化的横切关注点所带来的问题

横切关注点是指跨越应用程序多个模块的功能。

1、追踪方法:大多应用程序都有一个通用的需求,即在程序执行期间追踪正在发生的活动。在Java平台上,有多个可供选择的日志实现。

如果希望应用程序和具体的日志实现无关联,Apache Commons Logging库比较适合,他提供了与实现无关的抽象API,不用修改代码即可在不同的日志实现之间进行切换。

可以用来记录方法的开始和结束,还可以记录方法的参数和返回值。

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

....

private Log log = LogFactory.getLog(this.getClass);

....

log.info(“the method begin with” + a);

....

你可以自由的选择Commons Logging库所支持的日志实现。目前它主要支持Apache的Log4J库和JDK Logging API,最好选前者,它更好配置。

Log4J支持6种日志级别,用于设置日志信息的紧急程度。由高到低为fatal、error、warn、info、debug和trace。在Log4J配置文件log4j.properties里,可以设置应用程序的根(默认)日志级别error,则意味着默认情况下只会输出fatal和error级别的日志信息。也可以编程中手动设置。

       2、验证参数(出现横切关注点)

为方法制造一个参数约束:必须为正数。那么每个方法的开始都需要调用validate()方法,如果为负数则抛出IllegalArgumentException。

3、上面就暴露出一个问题:越来越多的非业务需求(日志、验证)加入后,业务方法的内容急剧膨胀。这些属于系统范围的需求通常需要跨越多个模块,所以为了将它们与核心业务区别开来,就把他们称作横切关注点

企业级应用程序中典型的横切关注点包括:日志、验证(包括身份验证)、缓存、连接池和事务。

 

非模块化的横切关注点导致两个主要问题:

a.代码混乱(code tangling),每个方法在处理核心业务的时候还必须兼顾其他的关注点,这也会使得代码的可维护性和复用性变得很差。

       b.代码分散(code scattering),以日志需求为例,为了满足这单一的需求,就不得不在多个模块里多次重复相同的代码;日志需求发生变化,则必须修改所有模块,这很难保证日志需求的一致性,若遗漏一处后果重大。

 

模块化横切关注点的作用:将日志和验证关注点从核心业务中分离出来。

 

 

5.2使用动态代理模块化横切关注点 (难度大)

问题:横切关注点模块化

方案:用代理的设计模式将横切关注点从核心业务离分离出来。

代理模式是23中GoF面向对象设计模式里的一种,属于“结构模式”。原理:使用一个代理将对象包装起来,然后用该代理对象取代原始对象,任何对原始对象的调用首先都要经过代理。这也说明代理对象负责决定是否以及何时将方法调用转发到原始对象上。而且围绕着每个方法的调用,代理对象也可执行一些额外的任务。

在Java里代理设计模式的实现的方法:

1.以纯面向对象的方式编写一个静态代理;缺点:需要使用专门的代理包装对象,意味着每个接口都需要编写一个代理类(低效)。2.JDK动态代理,动态的为任意对象创建代理;缺点/限制:被代理的对象必须至少实现一个接口,并且只有调用那些声明在接口里的方法才会经过代理。3.动态代理的优化——CGLIB代理,克服2中的缺点,可以处理类中所有声明的方法—可以不用实现任何接口。

实现:JDK动态代理模块化横切关注点。核心包java.lang.reflect. InvocationHandler/Method/Proxy。创建日志代理:创建一个具有调用处理程序的JDK动态代理实例,只需方法调用静态方法Proxy.newProxyInstance(…);验证代理,遍历参数数目来验证每个方法参数。

代理设计模式实现多个关注点——可以使用验证代理包装日志代理形成一个代理链,方法得先经过验证代理,再日志代理。

5.3使用经典的Spring通知来模块化横切关注点

问题:JDK动态代理太苛刻。

方案:对于横切关注点,AOP定义了一组高层次的概念:执行点执行的横切动作被封装在通知(advice)里。Spring AOP的4种通知类型,分别作用于执行点的不同时间。在正式的AOP定义里,多种类型的执行点:方法执行、构造器执行、字段访问。但Spring AOP只支持方法执行。

       4种通知类型:前置通知(方法执行前)、返回通知(方法返回结果后)、异常通知(方法抛出异常后)、环绕通知(围绕方法执行)。

实现:Spring AOP只为在它的IoC容器里声明的Bean处理横切关注点,所以在使用Spring AOP模块化横切关注点之前,必须将应用程序迁移到Spring IoC容器里——在spring的Bean配置文件里声明应用程序即可。

6.1在spring中启用AspectJ注解支持

问题:spring2.x支持在他的AOP框架中使用一Aspect注解编写的POJO切面。但是,首先必须在Spring IoC容器里启用AspectJ注解支持。

方案:Bean配置文件中定义控的XML元素:<aop:aspectj-autoproxy />即可

 

在apsectJ注解中,切面只是一个带有@AspectJ注解的Java类。AspectJ支持5种类型的通知注解:@Before @After @AfterReturning @AfterThrowing和@Around

@Aspect

public class CalculatorLoggingAspect {

       private Log log = LogFactory.getLog(this.getClass());

       @Before(“execution (* ArithmeticCalculator.add(..))”)

       public void logBefore(JoinPoint joinPoint) { //访问连接点

              log.info(“before”+joinPoint.getSignature().getName() );

       }

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章