欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

简单理解Spring之IOC和AOP及代码示例

程序员文章站 2024-02-25 08:37:28
spring是一个开源框架,主要实现两件事,ioc(控制反转)和aop(面向切面编程)。 ioc 控制反转,也可以称为依赖倒置。 所谓依赖,从程序的角度看,就是比如a...

spring是一个开源框架,主要实现两件事,ioc(控制反转)和aop(面向切面编程)。

ioc

控制反转,也可以称为依赖倒置。

所谓依赖,从程序的角度看,就是比如a要调用b的方法,那么a就依赖于b,反正a要用到b,则a依赖于b。所谓倒置,你必须理解如果不倒置,会怎么着,因为a必须要有b,才可以调用b,如果不倒置,意思就是a主动获取b的实例:bb=newb(),这就是最简单的获取b实例的方法(当然还有各种设计模式可以帮助你去获得b的实例,比如工厂、locator等等),然后你就可以调用b对象了。所以,不倒置,意味着a要主动获取b,才能使用b;到了这里,就应该明白了倒置的意思了。倒置就是a要调用b的话,a并不需要主动获取b,而是由其它人自动将b送上门来。

所谓控制反转,就是控制权的转移,举例说明:一个人要开车,正常情况下,人应该自己去找车,而实现控制反转后,人就不需要考虑车从哪里来了,直接开就行了,人就把找车的控制权转移给了别的对象。体会一下下面的代码

先定义一个接口car

public interface car {
  void go();
}

定义两种车

public class benz implements car {

  public void go() {
    system.out.println("benz go......");
  }
}

public class bmw implements car{

  public void go() {
    system.out.println("bmw go......");
  }
}

下面是人开车

public class person {

  car car=new benz();

  void drivecar(){
    system.out.println("begin drive");
    car.go();
  }
}

这是正常的代码控制流程,人想要开车,就要自己去实例化一辆车。但是,这样子的话,这个人就只能开一种车。怎么样才能让这个人能开各种车呢,就是要实现控制反转,也就是说,人不再去自己实例化车了,那人怎样得到车的对象呢?我们可以通过依赖注入(dependency injection,简称di)的方式来让人得到车的对象,从而实现控制反转。所以,我们要修改person类

public class person {

  car car=null;
  public person(car car){
    this.car=car;
  }

  void drivecar(){
    system.out.println("begin drive");
    car.go();
  }
}

现在的person类已经不自己实例化车的对象了,而是通过构造函数来获得车的对象,所以,这个类就可以开各种车了,只要这个车实现了car接口就可以。看一下如何使用person类

public static void main(string[] args) {
  person p=new person(new benz());
  p.drivecar();
}

现在的person类可以开不止一种车,只要你通过构造函数传递进来。在这个例子中,car对象就是person类的依赖,当我们实例化person类时,将一个car的实例传递给person类,就是依赖注入,我们的person类从而实现了控制反转。

控制反转到底反转了什么?有种说法是这样的:所谓控制反转,反转的是获取对象依赖的过程。控制权反转后,获取依赖对象的过程由自身管理变为由ioc容器注入。

spring实现依赖注入的方式

在上面的这行代码中person p=new person(new benz());,我们通过手动的方式new了一个benz()的对象,然后将其注入到person类中。而spring不这么干,因为spring觉得,你这行代码实例化了一个具体的benz类,如果你以后想要在这里实例化一个bmw类的话,岂不是要修改代码?那我干脆写到配置文件里好了,即便你将来要该注意,至少不需要修改代码,于是就有了下面的配置

<beans>
  <bean id="car" class="com.xxx.benz" />
  <bean id="person" class="com.xxx.person" >
    <property name="car" ref="car" />
  <bean/>
</beans>

然后,spring再提供一些机制,从配置文件中获取person类的对象时,它所以来的car对象会被装配进来,而person对象不需要关心到底是哪个具体的类被传递进来了。所以,spring作为一个ioc框架主要做了两步:创建对象和组装对象之间的关系。

aop

aop(aspect oriented programming)是面向切面编程,下面我来举例说明什么是切面。在一个完整的网站项目中,很多模块都需要做日志记录,很多地方都需要做登录判断,很多地方都需要做异常处理。日志记录,登录判断,异常处理等这些逻辑,就是所谓的切面。假设我将这些切面的逻辑写得到处都是,那么代码的可维护性就可想而知了。aop就是为了实现关注点分离,将这些切面的逻辑抽出来写到单独的类中,然后再想办法将他们与一般的模块组装到一块来执行,普通模块甚至都不知道他们已经和切面组装到一块了。

 面向切面编程的目标就是分离关注点。什么是关注点呢?就是你要做的事,就是关注点。假如你是个公子哥,没啥人生目标,天天就是衣来伸手,饭来张口,整天只知道玩一件事!那么,每天你一睁眼,就光想着吃完饭就去玩(你必须要做的事),但是在玩之前,你还需要穿衣服、穿鞋子、叠好被子、做饭等等等等事情,这些事情就是你的关注点,但是你只想吃饭然后玩,那么怎么办呢?这些事情通通交给别人去干。在你走到饭桌之前,有一个专门的仆人a帮你穿衣服,仆人b帮你穿鞋子,仆人c帮你叠好被子,仆人c帮你做饭,然后你就开始吃饭、去玩(这就是你一天的正事),你干完你的正事之后,回来,然后一系列仆人又开始帮你干这个干那个,然后一天就结束了!

aop的好处就是你只需要干你的正事,其它事情别人帮你干。也许有一天,你想裸奔,不想穿衣服,那么你把仆人a解雇就是了!也许有一天,出门之前你还想带点钱,那么你再雇一个仆人d专门帮你干取钱的活!这就是aop。每个人各司其职,灵活组合,达到一种可配置的、可插拔的程序结构。

从spring的角度看,aop最大的用途就在于提供了事务管理的能力。事务管理就是一个关注点,你的正事就是去访问数据库,而你不想管事务(太烦),所以,spring在你访问数据库之前,自动帮你开启事务,当你访问数据库结束之后,自动帮你提交/回滚事务!

看下面的代码,看不懂没关系

<bean id="audience" class="com.springinaction.springidol.audience" />
<aop:config>
 <aop:aspect ref="audience">
  <aop:pointcut id="performance" expression=
    "execution(* com.springinaction.springidol.performer.perform(..))" 
    />

  <aop:before 
    pointcut-ref="performance"
    method="takeseats" /> <!--<co id="co_refpointcut"/>-->
  <aop:before 
    pointcut-ref="performance"
    method="turnoffcellphones" /> <!--<co id="co_refpointcut"/>-->
  <aop:after-returning
    pointcut-ref="performance" 
    method="applaud" /> <!--<co id="co_refpointcut"/>-->
  <aop:after-throwing 
    pointcut-ref="performance" 
    method="demandrefund" /> <!--<co id="co_refpointcut"/>-->
 </aop:aspect>
</aop:config>

上面配置的大概意思是,当performer.perform方法将要发生时,spring框架中的代理会将目标方法(performer.perform())拦截下来,执行目标方法前先执行audience.takeseats()和audienceturn.offcellphones()方法,然后运行目标方法,当目标方法执行完毕返回时,再运行audienceturn.applaud()方法。如果目标方法不幸抛出了异常,代理会运行audienceturn.demandrefund()方法。总之,spring的代理类全方位地监控了目标方法的执行,而目标方法只专注于自己的事情,甚至都不知道代理类的存在。

总结

以上就是本文关于简单理解spring之ioc和aop及代码示例的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站:

spring的ioc模拟实现详细介绍

spring aop拦截-三种方式实现自动代理详解

如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!