浅析Spring AOP(面向方面编程)

SpringAOP提供的优势

1、允许开发者声明企业级服务,比如:事务服务、安全性服务。EJB组件能够使用J2EE容器提供声明式服务。但是需要借助于EJB组件,而SpringAOP却不需要EJB容器,即借助于Spring的事务抽象框架能够在EJB容器外部使用企业级、声明式服务。

2、开发者可以开发满足业务需求的自定义方面。类似于JBOSS服务器中拦截器开发一样,如果标准的J2EE安全性不能满足业务需求,则必须开发拦截器。

3、开发SpringAOP advice很方便,这些AOP Advice不仅仅POJO类,借助于Spring提供的ProxyFactoryBean,能够迅速的搭建Spring AOP Advice

Spring AOP的装备

1、before装备:在执行目标之前执行的装备

使用接口org.springframework.aop.MethodBeforeAdvice

源码如下:

public class LoggingBeforeAdvice implements MethodBeforeAdvice{
    protected static final Log log = LogFactory.getLog(LoggingBeforeAdvice.class);
    public void before(Method arg0,Object[] arg1,Object arg2){
        // before do something
    }
}
该方法在

调用目标操作之前调用,这很适用于那些有安全性要求的方法,即在调用目标操作之前检查客户身份。开发者还需要提供application.xml文件。

<beans>
<bean id="helloworldbean" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="proxyInterfaces">
        <value>com.openv.spring.IHelloWorld</value>
    </property>
    <property name="target">
        <ref local="helloworldbeanTarget"/>
    </property>
    <property name="interceptorNames">
        <list>
            <value>loggingBeforeAdvisor</value>
        </list>
    </property>
</bean>
<bean id="helloworldbeanTarget" class="com.openv.spring.HelloWorld" />
<bean id="loggingBeforeAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
    <property name="advice">
        <ref local="loggingBeforeAdvice" />
    </property>
    <property name="pattern">
        <value>.*</value>
    </property>
</bean>
<bean id="loggingBeforeAdvice" class="com.openv.spring.LoggingBeforeAdvice" />
</beans>

其中借助了RegexpMethodPointcutAdvisor类实现了对LoggingBeforeAdvice装备的集成,以完成pointcut和拦截器的定义。

2、Throws装备:如果目标操作在执行过程中抛出了异常,该装备会执行,可以采用Java捕捉异常而不用对异常信息或throwable进行造型

使用接口org.springframework.aop.ThrowsAdvice

对于处理事务或者特定业务需求很有帮助,源码如下:

public interface IHelloWorld{
    public String getContext(String helloworld) throws Exception;
}

public class HelloWorld implements IHelloWorld{
    protected static final Log log = LogFactory.getLog(HelloWorld.class);

    public String getContext(String helloworld) throws Exception{
        // do something
        throw new Exception();
    }
}

LoggingThrowsAdvice的装备代码如下:

public class LoggingThrowsAdvice implements ThrowsAdvice{
    protected Log log = LogFactory.getLog(LoggingThrowsAdvice.class);
    public void afterThrowing(Method method,Object[] args,Object target,Throwable subclass){
        // throw some Exception
    }
}

其实现了afterThrowing方法,当异常抛出时,该装备即被激活,具体的Spring配置文件如下:

<bean id="helloworldbean" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="proxyInterfaces">
        <value>com.openv.spring.IHelloWorld</value>
    </property>
    <property name="target">
        <ref local="helloworldbeanTarget" />
    </property>
    <property name="interceptorNames">
        <list>
            <value>loggingThrowsAdvisor</value>
        </list>
    </property>
</bean>
<bean id="helloworldbeanTarget" class="com.openv.spring.HelloWorld" />
<bean id="loggingThrowsAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
    <property name="advice">
        <ref local="loggingThrowsAdvice">
    </property>
    <property name="pattern">
        <value>.*</value>
    </property>
</bean>
<bean id="loggingThrowsAdvice" class="com.openv.spring.LoggingThrowsAdvice" />

应用抛出Exception后,LoggingThrowsAdvice的AfterThrowing即被激活

3、After装备:在执行目标之后执行的装备

After状态在执行密保操作之后执行装备中的afterReturnning方法。具体的LoggingAfterAdvice实现如下:

public class LoggingAfterAdvice implements AfterRuturningAdvice{
    protected static final Log log = LogFactory.getLog(LoggingAfterReturnningAdvice.class);
    public void afterReturnning(Object object,Method m,Object[] args,Object target) throws Throwable(
        // after do something
    )
}
配置文件:
<bean id="helloworldbean" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="proxyInterfaces">
        <value>com.openv.spring.IHelloWorld</value>
    </property>
    <property name="target">
        <ref local="helloworldbeanTarget" />
    </property>
    <property name="interceptorNames">
        <list>
            <value>loggingAfterAdvisor</value>
        </list>
    </property>
</bean>

<bean id="helloworldbeanTarget" class="com.openv.spring.HelloWorld"/>
<bean id="loggingAfterAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
    <property name="advisor">
        <ref local="loggingAfterAdvice" />
    </property>
    <property name="pattern">
        <value>.*</value>
    </property>
</bean>

<bean id="loggingAfterAdvice" class="com.openv.spring.LoggingAfterAdvice" />

使用接口org.springframework.aop.AfterReturningAdvice

对于代理Java接口的场景,Spring默认时是采用动态代理实现的,对于代理Java类的场景Spring采用动态字节码(byte-code)生成技术,比如使用了CGLIB库。

4、Around装备:在调用方法前后执行的装备。功能最强大,能够在目标操作执行前后实现特定的行为,使用灵活。

使用接口org.springframework.aop.MethodInterceptor

功能最强大,灵活性最好,能够在执行目标前后执行,这对一些需要做资源初始化和释放操作的应用特别有用,具体代码分析如下:

public class LoggingAroundAdvice implements MethodInterceptor{
    protected static final Log log = LogFactory.getLog(LoggingAroundAdvice.class);
    public Object invoke(MethodInvocation invocation) throws Throwable{
        log.info("before:The Invocation of getContent()");
        invocation.getArguments()[0] = "jader";
        invocation.proceed();
        log.info("after:The Inovation of getContent()");

        return null;
    }
}
配置文件如下:
<bean id="helloworldbean" class="org.springframework.aop.framework.ProxyFactoryBean" >
    <property name="proxyInterfaces">
        <value>com.openv.spring.IHelloWorld</value>
    </property>
    <property name="target">
        <ref local="helloworldbeanTarget" />
    </property>
    <property name="interceptorNames">
        <list>
            <value>loggingAroundAdvisor</value>
        </list>
    </property>
</bean>
<bean id="loggingAroundAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
     <property name="advice">
        <ref local="loggingAroundAdvice">
     </property>
     <property name="pattern">
        <value>.*</value>
    </property>
</bean>
<bean id="loggingAroundAdvice" class="com.openv.spring.LoggingAroundAdvice" />

5、Introduction装备:能够为类新增方法,最复杂

这几种接口之间的关系:

ProxyFactoryBean

ProxyFactoryBean引入了间接层。通过名字或者id(helloworldbean)获得的引用对象并不是ProxyFactoryBean实例本身,而是ProxyFactoryBean中getObject方法实现返回的对象。其中getObject方法将创建AOP代理,并将目标对象包裹(wrapper)在其中。那么ProxyFactoryBean到底是什么?

ProxyFactoryBean实现了org.springframework.beans.factory.FactoryBean接口,本身也是JavaBean,下面是其类图:

主要有以下几个属性:

proxyInterfaces:接口构成字符串列表,即接口集合

proxyTargetClass:是否使用CGLIB代理目标类的标志位动态代理能够对接口指定,如果目标是类则无能无力,因此需要借助于CGLIB库,实现类的子类,从而起到代理类的作用。

interceptorNames:拦截器名构成的字符串列表,拦截器集合

target:执行目标类

SingleTon:单实例的标志位,每次调用ProxyFactoryBean的getObject方法时是返回同一个对象还是返回不同的对象。

下面看下具体的代码:

public class HelloClient{
    protected static final Log log = LogFactory.getLog(HelloClient.class);
    public static void main(String[] args){
        // 创建LoggingAroundAdvice装备
        Advice advice = new LoggingAroundAdvice();
        // 创建ProxyFactory,从而不需要借助Spring IOC容器提供反转功能
        ProxyFactory factory = new ProxyFactory(new HelloWorld());
        factory.addAdviced(advice);
        IHelloWorld hw = (IHelloWorld)factory.getProxy();
        log.info(hw.getContext("jader"));
    }
}

通过手工创建AOP代理能够摆脱Spring IOC容器的依赖。

Spring框架开发team推荐:借助于Spring IOC框架自动创建AOP代理,并将有关AOP代理的Java代理通过Spring配置文件配置。

FactoryBean在Spring框架起了很重要的作用,ProxyFactoryBean实现了FactoryBean接口,借助于ProxyFactoryBean能够实现各种业务需求,但要求去额外开发很多辅助业务操作,比如事务、数据库连接。

对象池

先研究下application.xml

// 借助于spring框架对commons pool的有效支持,能够实现对helloworldbeanTarget的有效池化

// 同时还能设置对象池的最大数量

<bean id="poolTargetSource" class="org.springframework.aop.target.CommonsPoolTargetSource">
    <property name="targetBeanName">
        <value>helloworldbeanTarget</value>
    </property>
    <property name="maxSize">
        <value>25</value>
    </property>
</bean>

// 通过ProxyFactoryBean中指定targetSource属性,便能够使用到poolTargetSource提供的强大功能

<bean id="helloworldbean" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="targetSource">
        <ref local="poolTargetSource" />
    </property>
    <property name="interceptorNames">
        <list>
            <value>loggingAroundAdvisor</value>
        </list>
    </property>
</bean>
时间: 2024-11-05 15:56:19

浅析Spring AOP(面向方面编程)的相关文章

深入探索spring技术内幕(七): 配置Spring AOP面向切面编程

一. AOP一些概念 Aspect( 切面 ): 指横切性关注点的抽象即为切面, 它与类相似, 只是两者的关注点不一样, 类是对物体特征的抽象, 而切面横切性关注点的抽象. joinpoint( 连接点 ): 指那些被拦截到的点. 在spring中, 这些点指的是方法, 因为spring只支持方法类型的连接点, 实际上joinpoint还可以是field或类构造器) Pointcut( 切入点 ): 指我们要对那些joinpoint进行拦截的定义. Advice( 通知 ): 指拦截到joinp

浅谈Spring AOP 面向切面编程 最通俗易懂的画图理解AOP、AOP通知执行顺序~

简介 我们都知道,Spring 框架作为后端主流框架之一,最有特点的三部分就是IOC控制反转.依赖注入.以及AOP切面.当然AOP作为一个Spring 的重要组成模块,当然IOC是不依赖于Spring框架的,这就说明你有权选择是否要用AOP来完成一些业务. AOP面向切面编程,通过另一种思考的方式,来弥补面向对象编程OOP当中的不足,OOP当中最重要的单元是类,所以万物皆对象,万物皆是 对象类.而在AOP的模块单元中,最基础的单元是切面,切面对切点进行模块化的管理. 最后再提一句:Spring当

Spring AOP 面向切面编程

AOP 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型.利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率. 在Spring中提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例

spring AOP面向切面编程学习笔记

一.面向切面编程简介: 在调用某些类的方法时,要在方法执行前或后进行预处理或后处理:预处理或后处理的操作被封装在另一个类中.如图中,UserService类在执行addUser()或updateUser方法前开启事务,执行完后要提交事务:而几乎所有数据库操作都是如此,那么就可以将事务操作的方法提取出封装到一个类里.然后再利用代理类进行处理(目标类方法增强),返回代理类对象 二.AOP相关术语 Target:目标类,需要被增强的类. JoinPoint:连接点,目标类上需要被增强的方法.(这些方法

【spring-boot】spring aop 面向切面编程初接触

众所周知,spring最核心的两个功能是aop和ioc,即面向切面,控制反转.这里我们探讨一下如何使用spring aop. 1.何为aop aop全称Aspect Oriented Programming,面向切面,AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果.其与设计模式完成的任务差不多,是提供另一种角度来思考程序的结构,来弥补面向对象编程的不足. 通俗点讲就是提供一个为一个业务实现提供切面注入的

【Spring系列】Spring AOP面向切面编程

前言 接上一篇文章,在上午中使用了切面做防重复控制,本文着重介绍切面AOP. 在开发中,有一些功能行为是通用的,比如.日志管理.安全和事务,它们有一个共同点就是分布于应用中的多处,这种功能被称为横切关注点(cross-cutting concerns). DI(依赖注入)有助于应用对象之间的解耦,而AOP可以实现横切关注点与他们所影响的对象之间的解耦. 面向切面编程在Spring AOP中有4种类型的调用,方法调用的之前.后.异常增加其他方法,方法调用的前和后调用其他方法,将方法中的参数传递给其

十二.Spring AOP面向切面编程

什么是AOP? AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. AOP的第一个案例 要求:使用AOP实现日志记录功能,核心模块和增强单独开发,运行时组装 1.创建接口HelloDao.HelloService. 创建接口类HelloDaoImpl.HelloServiceImpl并实现dao层接口 public interface IHolleDao { public void print

Spring AOP面向切面编程详解

前言 AOP即面向切面编程,是一种编程思想,OOP的延续.在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等等.在阅读本文前希望您已经对Spring有一定的了解 注:在能对代码进行添加注解方式实现AOP的话,并不推荐使用XML方式.换言之在XML方式配置更适用于不能对代码添加注解的情况下(注解配置方式推荐值>XML配置方式推荐值) AOP相关术语 1.通知(Advice):在切面的某个特定的连接点上执行的动作,即当程序到达一个执行点后会执行相对应的一段代码,也称为增强处理.通知

从源码入手,一文带你读懂Spring AOP面向切面编程

之前<零基础带你看Spring源码--IOC控制反转>详细讲了Spring容器的初始化和加载的原理,后面<你真的完全了解Java动态代理吗?看这篇就够了>介绍了下JDK的动态代理. 基于这两者的实现上,这次来探索下Spring的AOP原理.虽然AOP是基于Spring容器和动态代理,但不了解这两者原理也丝毫不影响理解AOP的原理实现,因为大家起码都会用. AOP,Aspect Oriented Programming,面向切面编程.在很多时候我们写一些功能的时候,不需要用到继承这么

Spring AOP面向切面编程

出处:http://yangfei520.blog.51cto.com/1041581/1273069 前两天,在给新入职的同事做技术介绍时,讲到spring的AOP.使我又一次认识到,对于AOP,特别是spring AOP的理解,虽然大家都能说上来几句,但是许多人认识并不太全面,甚至可以说是一知半解----即使是对于那些已经有过几年开发经验的工程师也是如此.所以,回来之后,我干脆对这块东西做了个肤浅的小结,以便再有类似任务时,直接拿来给大家借鉴. AOP(Aspect-Oriented Pro