反向控制和面向切面编程在Spring的应用
Spring是为简化企业级系统开发而诞生的,Spring框架为J2EE应用常见的问题提供了简单、有效的解决方案,使用Spring,你可以用简 单的POJO(Plain Old Java Object)来实现那些以前只有EJB才能实现的功能。这样不只是能简化服务器端开发,任何Java系统开发都能从Spring的简单、可测试和松耦合 特征中受益。可以简单的说,Spring是一个轻量级的反向控制(IoC)和面向切面编程(AOP)容器框架[3]。Spring IoC,借助于依赖注入设计模式,使得开发者不用理会对象自身的生命周期及其关系,而且能够改善开发者对J2EE模式的使用;Spring AOP,借助于Spring实现的拦截器,开发者能够实现以声明的方式使用企业级服务,比如安全性服务、事务服务等。Spring IoC和 Spring ; AOP组合,一起形成了Spring,这样一个有机整体,使得构建轻量级的J2EE架构成为可能,而且事实证明,非常有效。没有Spring IoC的Spring AOP是不完善的,没有Spring AOP的Spring IoC是不健壮的。本文是以Spring架构的成功的实际商务系统项目为背景,阐述了反向控制原理和面向切面的编程技术在Spring框架中的应用,同时 抽取适量代码示意具体应用,并和传统开发模式进行对比,展示了Spring framework的简单,高效,可维护等优点。
1、Spring IoC 1.1 依赖注入原理
反向控制是Spring框架的核心。但是,反向控制是什么意思?到底控制的什么方面被反向了呢?2004年美国专家Martin Fowler发表了一篇论文《Inversion of Control Containers and the Dependency Injection pattern》阐述了这个问题,他总结说是获得依赖对象的方式反向了,根据这个启示,他还为反向控制提出了一个更贴切的名字:Dependency Injection(DI 依赖注入)。
通常,应用代码需要告知容器或框架,让它们找到自身所需要的类,然后再由应用代码创建待使用的对象实例。因此,应用代码在使用实例之前,需要创建对象 实例。然而,IoC模式中,创建对象实例的任务交给IoC容器或框架(实现了IoC设计模式的框架也被称为IoC容器),使得应用代码只需要直接使用实 例,这就是IoC。相对IoC 而言,“依赖注入”的确更加准确的描述了这种设计理念。所谓依赖注入,即组件之间的依赖关系由容器在运行期决定,形象的来说,即由容器动态的将某种依赖关 系注入到组件之中。
1.2 IoC在Spring中的实现
任何重要的系统都需要至少两个相互合作的类来完成业务逻辑。通常,每个对象都要自己负责得到它的合作(依赖)对象。你会发现,这样会导致代码耦合度高 而且难于测试。使用IoC,对象的依赖都是在对象创建时由负责协调系统中各个对象的外部实体提供的,这样使软件组件松散连接成为可能。下面示意了 Spring IoC 应用,步骤如下:
(1)定义Action接口,并为其定义一个execute方法,以完成目标逻辑。多年前,GoF在《Design Pattern:Elements of Reusable Object-Oriented Software》一书中提出“Programming to an Interface,not an implementation”的原则,这里首先将业务对象抽象成接口,正是为了实施这个原则。
(2)类UpperAction实现Action接口,在此类中,定义一个String型的域message,并提供相应的setter和getter方法,实现的execute方法如下:
public String execute (String str) {
return (getMessage () + str).toUpperCase () ;
}
(3)编写Spring配置文件(bean.xml)
<beans>
<bean id="testAction" class="net.chen.spring.qs.UpperAction">
<property name="message">
<value>HeLLo</value>
</property>
</bean>
</beans>
(4)测试代码
public void testQuickStart () {
ApplicationContext ctx=new
FileSystemXmlApplicationContext ("bean.xml");
Action a= (Action) ctx.getBean ("testAction");
System.out.println (a. execute ("haha"));
}
上面的测试代码中,我们根据"bean.xml"创建了一个ApplicationContext实例,并从此实例中获取我们所需的Action实现,运行测试代码,我们看到控制台输出:
……
HELLO haha
仔细观察一下上面的代码,可以看到:
(1)我们的组件并不需要实现框架指定的接口,因此可以轻松的将组件从Spring中脱离,甚至不需要任何修改,这在基于EJB框架实现的应用中是难以想象的。
(2)组件间的依赖关系减少,极大改善了代码的可重用性。Spring的依赖注入机制,可以在运行期为组件配置所需资源,而无需在编写组件代码时就加以指定,从而在相当程度上降低了组件之间的耦合。
Spring给我们带来了如此这般的好处,那么,反过来,让我们试想一下,如果不使用Spring框架,回到我们传统的编码模式,情况会是怎样呢?
首先,我们必须编写一个配置文件读取类,以实现Message属性的可配置化。
其次,得有一个Factory模式的实现,并结合配置文件的读写完成Action的动态加载。于是,我们实现了一个ActionFactory来实现这个功能:
public class ActionFactory {
public static Action getAction (String actionName) {Properties pro = new Properties ();
try {
pro.load (new FileInputStream ("config.properties"));
String actionImplName =(String)pro.get(actionName);
String actionMessage =(String) pro.get (actionName+"_msg");
Object obj =Class.forName (actionImplName).newInstance ();
BeanUtils.setProperty(obj,"message",actionMessage);
return (Action) obj;
} catch (FileNotFoundException e) {
……
}
}
配置文件则采用properties文件形式如下所示:
TheAction=net.chen.spring.qs.UpperAction
TheAction_msg=HeLLo
测试代码也作相应修改。现在不论实现的好坏,总之通过上面新增的多行代码,终于实现了类似的功能。如果现在有了一个新的需求,这样这个 ActionFactory每次都新建一个类的实例,显然这对系统性能不利,考虑到我们的两个Action都是线程安全的,修改一下 ActionFactory,保持系统中只有一个Action实例供其它线程调用。另外Action对象创建后,需要做一些初始化工作。修改一下 ActionFactory,使其在创建Action实例之后,随即就调用Action.init方法执行初始化。Action的处理这样就差不多了。下 面我们来看看另外一个Factory
……
往往这些系统开发中最常见的需求,会导致我们的代码迅速膨胀,而Spring IoC的出现,则大大缓解了这样的窘境。通过以上实例,可以看出,Spring IoC为我们提供了如下几方面的优势:
(1)应用组件不需要在运行时寻找其协作者,因此更易于开发和编写应用;
(2)由于借助于IoC容器管理组件的依赖关系,使得应用的单元测试和集成测试更利于展开;
(3)通常,在借助于IoC容器关系业务对象的前提下,很少需要使用具体IoC容器提供的API,这使得集成现有的遗留应用成为可能。
因此,通过使用IoC能够降低组件之间的耦合度,最终,能够提高类的重用性,利于测试,而且更利于整个产品或系统集成和配置。
查看关于 Spring 的全部文档 观察:Spring 2006 年度风光回顾 人物:Spring之父Rod Johnson
2、Spring AOP
2.1 面向切面编程基础
通常,系统由很多组件组成,每个组件负责一部分功能,然而,这些组件也经常带有一些除了核心功能之外的附带功能 。系统服务如日志、事务管理和安全经常融入到一些其他功能模块中。这些系统服务通常叫做交叉业务,这是因为它们总是分布在系统的很多组件中。通过将这些业 务分布在多个组件中,给我们的代码引入了双重复杂性。
(1) 实现系统级业务的代码在多个组件中复制。这意味着如果你要改变这些业务逻辑,你就必须到各个模块去修改。就算把这些业务抽象成一个独立模块,其它模块只是调用它的一个方法,但是这个方法调用也还是分布在很多地方。
(2) 组件会因为那些与自己核心业务无关的代码变得杂乱。一个向地址录中添加条目的方法应该只关心如何添加地址,而不是关心它是不是安全或支持事务的。
此时,我们该怎么办呢?这正是AOP用得着的地方。AOP帮助我们将这些服务模块化,并把它们声明式地应用在需要它们的地方,使得这些组件更加专注于自身业务,完全不知道其它涉及到的系统服务。
这里的概念切面,就是我们要实现的交叉功能,是应用系统模块化的一个方面或领域。切面的最常见例子就是日志记录。日志记录在系统中到处需要用到,利用 继承来重用日志模块是不合适的,这样,就可以创建一个日志记录切面,并且使用AOP在系统中应用。下图展示了切面应用方式
图表 1 应用切面
其中,通知Advice是切面的实际实现。连接点Joinpoint是应用程序执行过程中插入切面的地点,这个地点可以是方法调用,异常抛出,甚至可 以是要修改的字段,切面代码在这些地方插入到你的应用流程中,添加新的行为。切入点Pointcut定义了Advice应该应用在那些连接点,通常通过指 定类名和方法名,或者匹配类名和方法名式样的正则表达式来指定切入点。
2.2 AOP在Spring中的实现
基于AOP,业界存在各种各样的AOP实现,比如,JBoss AOP、Spring AOP、AspectJ、Aspect Werkz等。各自实现的功能也不一样。AOP实现的强弱在很大程度上取决于连接点模型。目前,Spring只支持方法级的连接点。这和一些其他AOP框 架不一样,如AspectJ和JBoss,它们还提供了属性接入点,这样可以防止你创建特别细致的通知,如对更新对象属性值进行拦截。然而,由于 Spring关注于提供一个实现J2EE服务的框架,所以方法拦截可以满足大部分要求,而且Spring的观点是属性拦截破坏了封装,让Advice触发 在属性值改变而不是方法调用上无疑是破坏了这个概念。
Spring的AOP框架的关键点如下:
(1)Spring实现了AOP联盟接口。在Spring AOP中,存在如下几种通知(Advice)类型
Before通知:在目标方法被调用前调用,涉及接口org.springframework.aop.MethodBeforeAdvice;
After通知:在目标方法被调用后调用,涉及接口为org.springframework.aop.AfterReturningAdvice;
Throws通知:目标方法抛出异常时调用,涉及接口org.springframework.aop.MethodBeforeAdvice;
Around通知:拦截对目标对象方法调用,涉及接口为org.aopalliance.intercept.MethodInterceptor。
(2)用java编写Spring通知,并在Spring的配置文件中,定义在什么地方应用通知的切入点。
(3)Spring的运行时通知对象。代理Bean只有在第一次被应用系统需要的时候才被创建。如果你使用的是 ApplicationContext,代理对象在BeanFactory载入所有Bean的时候被创建。Spring有两种代理创建方式。如果目标对象 实现了一个或多个接口暴露的方法,Spring将使用JDK的java.lang.reflect.Proxy类创建代理。这个类让Spring动态产生 一个新的类,它实现所需的接口,织入了通知,并且代理对目标对象的所有请求。如果目标对象没有实现任何接口,Spring使用CGLIB库生成目标对象的 子类。在创建这个子类的时候,Spring将通知织入,并且将对目标对象的调用委托给这个子类。此时,需要将Spring发行包lib/cglib目录下 的JAR文件发布到应用系统中。
2.3 Spring AOP的优势
借助于Spring AOP,Spring IoC能够很方便的使用到非常健壮、灵活的企业级服务,是因为Spring AOP能够提供如下几方面的优势:
(1)允许开发者使用声明式企业服务,比如事务服务、安全性服务;EJB开发者都知道,EJB组件能够使用J2EE容器提供的声明式服务,但是这些服务要借助于EJB容器,而Spring AOP却不需要EJB容器,借助于Spring的事务抽象框架就可以这些服务。
(2)开发者可以开发满足业务需求的自定义切面;
(3)开发Spring AOP Advice很方便。因为这些AOP Advice仅是POJO类,借助于Spring提供的ProxyFactoryBean,能够快速的搭建Spring AOP Advice。
3、结语
本文详细阐述了Spring背后的IoC原理和AOP技术,以实际成功项目为背景,抽取简短片断,展示了Spring架构J2EE应用系统的原理。 Spring IoC借助于依赖注入机制,减轻了组件之间的依赖关系,同时也大大提高了组件的可移植性,组件得到了更多的重用机会。借助于Spring AOP,使得开发者能声明式、基于元数据访问企业级服务,AOP合理补充了OOP技术,Spring AOP合理地补充了Spring IoC容器。Spring IoC与Spring AOP组合,使得Spring成为成功的J2EE架构框架,并能与标准的EJB等标准对抗,EJB不再是必需品。Spring已经冲入了J2EE的核心, 将引领整个J2EE开发、架构的方向。
- 大小: 5.6 KB
分享到:
相关推荐
编程选择题40道:Spring框架:依赖注入与面向切面编程.Tex.docx
快速熟悉相关内容,编写基于Spring框架技术的依赖注入和面向切面编程的相关代码,掌握Spring框架技术中依赖注入和面向切面编程的具体过程和基本要素,具备编写具有松耦合和面向切面特点的应用程序的能力。...
Java中的AOP(面向切面编程)是一种编程范式,旨在将关注点分离,使得系统设计更为模块化,提高代码的可复用性和可维护性。AOP在Spring框架中得到了广泛的应用,允许开发者定义“切面”,这些切面可以包含业务逻辑的...
3. 面向切面编程(AOP):面向切面编程是 Spring 框架的另一个核心概念,它可以将公共业务集中处理,实现代码的复用和灵活性。 Spring 框架的结构由 7 个核心模块组成: 1. Spring Core:主要模块(组件),...
1. **Spring Core**:提供了Spring框架的基础,包括依赖注入(DI)和面向切面编程(AOP)的基础支持。它是所有其他模块的基础。 2. **Spring AOP**:支持面向切面编程,允许开发者定义方法拦截器和切入点,从而分离...
Spring 提供了丰富的功能,包括但不限于依赖注入(DI)、面向切面编程(AOP)、事务管理、数据访问和集成、Web 应用开发等。在本压缩包中,包含了与Spring框架和AspectJ相关的关键组件。 首先,Spring 框架是Java...
Spring框架是Java开发中广泛应用的一个轻量级容器,它的核心特性是依赖注入(Dependency Injection,简称DI)和面向切面编程(Aspect Oriented Programming,简称AOP)。这两个特性极大地简化了Java应用程序的开发和...
这是AOP(面向切面编程)的一部分,它允许在目标方法执行前插入自定义的行为。 在Spring AOP中,前置通知是通过实现`org.aspectj.lang.annotation.Before`注解的方法来定义的。这样的方法将在目标方法被调用之前...
这个压缩包中的简单Java依赖注入框架,结合了面向切面编程(Aspect-Oriented Programming,简称AOP),提供了轻量级的理解Spring框架核心原理的方式。下面我们将深入探讨这两个关键概念。 首先,依赖注入的核心思想...
Spring的核心思想是通过依赖注入和面向切面编程,将企业级应用开发的各个层面进行解耦,从而使开发者能够集中于业务逻辑,而非复杂的底层实现。Spring3.X是Spring的一个重要分支,它在Spring技术栈中引入了多项改进...
Spring.NET 还提供了一些辅助工具,如AOP(面向切面编程)、数据访问支持、事务管理等。这些工具可以帮助开发者更高效地构建应用程序,减少重复工作。 ### 七、SpringNet_Lesson6 学习资源 压缩包文件`SpringNet_...
它们各自在Web应用程序的不同层面上发挥作用:Struts处理MVC模式中的Controller部分,Hibernate负责数据持久化,而Spring则提供了全面的依赖注入(Dependency Injection,DI)和面向切面编程(Aspect-Oriented ...
Spring框架是J2EE开发中的核心组件,它简化了企业级应用的开发过程,特别是在AOP(面向切面编程)和依赖注入(Dependency Injection,DI)方面。 AOP是一种编程范式,允许开发者定义“横切关注点”,即跨越多个对象...
通过了解和使用这些资源,开发者可以逐步掌握Spring框架的核心概念,如依赖注入和面向切面编程,并能够构建出基于Spring的复杂应用程序。同时,官方指导文档也非常重要,它会详细解释每个模块的用法和配置,帮助...
Spring框架是Java开发中不可或缺的一部分,它以其强大的依赖注入(DI)和面向切面编程(AOP)功能闻名。在Spring开发中,依赖包和配置文件是构建应用程序的基础。本篇将详细介绍Spring依赖包和配置文件的相关知识。 ...
2. **面向切面编程(AOP)**:Spring支持面向切面编程,允许开发者将横切关注点(如日志记录、事务管理等)与业务逻辑分离。 3. **数据访问和集成**:Spring提供了对各种数据访问技术的集成,包括JDBC、Hibernate、...
本文将深入探讨Spring框架的核心特性——依赖注入(Dependency Injection, DI)和面向切面编程(Aspect-Oriented Programming, AOP),以及如何解决循环依赖问题。 首先,依赖注入是Spring框架的核心理念之一,它的...
Spring4D 提供了面向切面编程的支持,允许开发者定义横切关注点,如日志、事务管理等,并将其与业务逻辑解耦。这使得代码更加整洁,减少了重复代码,提高了代码复用性。 **4. 数据访问层(Data Access Layer, DAL)...
Spring框架是Java开发中最广泛应用的轻量级框架之一,它以其IoC(Inversion of Control,控制反转)和AOP(Aspect Oriented Programming,面向切面编程)为核心特性,极大地简化了企业级应用的开发。这个"spring依赖...
5. **其他特性**:除了依赖注入,Spring.NET还提供了AOP(面向切面编程)、数据访问抽象、事务管理等企业级功能,可以构建复杂的企业级应用。 在这个例子中,通过学习如何配置和使用Spring.NET的依赖注入,我们可以...