AOP:面向切面

AOP: 面向切面编程,是一种编程思想,是对面向对象的一种补充.

:面向对象是静态角度考虑程序结构而面向切面是动态的考虑程序运行过程.

:面向切面编程是将交叉业务封装成切面,利用AOP容器功能将切面织入到主业务逻辑

Spring AOP是Spring框架中的一部分,但可以作为一个独立的模块单独存在。Spring AOP实现AOP技术从本质上来讲,是利用了JDK提供的动态代理技术。而从实际的实现方式来看,则是利用了IoC(Inversion of Control,反转模式)机制,同时采用了AOP联盟(AOP Alliance)的通用AOP接口。首先,Spring AOP通过xml配置文件配置了pointcut,并利用Interceptor(拦截机)作为设定的触发条件。Interceptor是由用户自定义的,它相当于是AOP中的advice,但该Interceptor需要实现AOP联盟的通用AOP接口,例如org.aopalliance.intercept.MethodInterceptor。最后定义一个Spring AOP ProxyFactory用于加载执行AOP组件,并利用IoC机制将advice注入到接口以及实现类中。

通知(advice): Spring 提供的一种切面,功能简单,只能讲切面织入到目标类的所有目标方法中而无法织入到指定目标方法中

/*AOP 小Demo*/
/*业务接口*/
public interface IService {
    public void doSome();
    public void doOther();
}
/*业务实现类*/
public class ServiceImpl implements IService{
    @Override
    public void doSome() {
        System.out.println("doSome 业务方法!");
    }
    @Override
    public void doOther() {
        System.out.println("doOther 业务方法");
    }
}
/*通知类: 前置通知*/
public class MyMethodAdvice implements MethodBeforeAdvice{
    public void before(Method arg0, Object[] arg1, Object arg2)
            throws Throwable {
        System.out.println("before method ......");
    }
}
/*测试类*/
public class MyTest {
    @Test
    public void test01(){
        String config = "com/xiehe/dao/applicationSpring.xml";
        //1.获取容器
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(config);
        //2.从容器中获取代理对象
        IService service= (IService) context.getBean("myServiceProxy");
        service.doSome();
        service.doOther();
    }
/*spring 配置文件: applicationSpring.xml*/
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
    <!-- bean definitions here -->
    <!-- 配置目标对象 -->
    <bean id="myService" class="com.xiehe.dao.ServiceImpl"></bean>
    <!-- 配置切面:通知 -->
    <bean id="myMethodAdvice" class="com.xiehe.dao.MyMethodAdvice"></bean>
    <!-- 配置代理: 此处使用了jdk 动态代理 -->
    <bean id="myServiceProxy"
    class="org.springframework.aop.framework.ProxyFactoryBean">
        <!-- 目标对象 -->
        <property name="target" ref="myService" />
        <!-- 接口 -->
        <property name="interfaces" value="com.xiehe.dao.IService" />
        <!-- 切面 -->
        <property name="interceptorNames" value="myMethodAdvice" />
    </bean>
</beans>

顾问(advisor):Spring 提供的另一种切面,可以完成复杂的切面织入功能(顾问 + 切入点)

在上例的spring 配置文件中配置顾问

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
    <!-- bean definitions here -->
    <!-- 配置目标对象 -->
    <bean id="myService" class="com.xiehe.dao8.ServiceImpl"></bean>
    <!-- 配置切面:通知 -->
    <bean id="myMethodAdvice" class="com.xiehe.dao8.MyMethodAdvice"></bean>
    <bean id="myMethodAdvice2" class="com.xiehe.dao8.MyMethodAdvice2"></bean>
    <!-- 配置顾问(通知 + 切入点):名称匹配 -->
    <bean id="myAdvisor"
    class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
        <!-- 通知-->
        <property name="advice" ref="myMethodAdvice" />
        <!-- 切入点-->
        <property name="mappedNames" value="doSome,doOther"/>
    </bean>
    <!-- 配置代理 : CGLIB -->
    <bean id="myServiceProxy"
    class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target" ref="myService" />
        <property name="interfaces" value="com.xiehe.dao8.IService" />
        <!-- 配置顾问-- >
        <property name="interceptorNames" value="myAdvisor"/>
        <!-- 指定优化的值为true: 强制使用CGLIB -->
        <property name="optimize" value="true"/>
    </bean>
</beans>

上例中,代理工厂bean(ProxyFactoryBean)一次只能为一个目标对象代理,Spring中提供自动代理来为所有的目标自动生成代理:

自动代理生成器均继承于bean 后处理器,BeanPostProcessor

1.DefaultAdvisorAutoProxyCreator (默认advisor自动代理生成器)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
    <!-- bean definitions here -->
    <!-- 配置目标对象 -->
    <bean id="myService" class="com.xiehe.dao10.ServiceImpl"></bean>
    <bean id="myService2" class="com.xiehe.dao10.ServiceImpl"></bean>
    <!-- 配置切面:通知 -->
    <bean id="myMethodAdvice" class="com.xiehe.dao10.MyMethodAdvice"></bean>
    <bean id="myMethodAdvice2" class="com.xiehe.dao10.MyMethodAdvice2"></bean>
    <!-- 配置顾问:名称匹配 -->
    <bean id="myAdvisor"
    class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
        <property name="advice" ref="myMethodAdvice" />
        <property name="mappedNames" value="doOther,doSome"/>
    </bean>
    <!-- 配置代理 -->
    <!-- 默认advisor配置自动代理 -->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
</beans>

默认advisor自动代理生成器 会给每一个目标对象生成代理,灵活性较差

BeanNameAutoProxyCreator(Bean名称自动代理生成器):可以指定给某一个或多个目标对象生成代理,灵活性好

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
    <!-- bean definitions here -->
    <!-- 配置目标对象 -->
    <bean id="myService" class="com.xiehe.dao10.ServiceImpl"></bean>
    <bean id="myService2" class="com.xiehe.dao10.ServiceImpl"></bean>
    <!-- 配置切面:通知 -->
    <bean id="myMethodAdvice" class="com.xiehe.dao10.MyMethodAdvice"></bean>
    <bean id="myMethodAdvice2" class="com.xiehe.dao10.MyMethodAdvice2"></bean>
    <!-- 配置顾问:名称匹配 -->
    <bean id="myAdvisor"
    class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
        <property name="advice" ref="myMethodAdvice" />
        <property name="mappedNames" value="doOther,doSome"/>
    </bean>
    <!-- 配置代理 -->
    <!-- 名称自动代理生成器 -->
 <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
        <property name="beanNames" value="myService2"/>
        <property name="interceptorNames" value="myMethodAdvice,myMethodAdvice2"/>
    </bean>
</beans>

由于 AspectJ 是 Java 语言语法和语义的扩展,所以它提供了自己的一套处理方面的关键字。除了包含字段和方法之外,AspectJ 的方面声明还包含pointcut和advice成员。示例中的pointcut使用了修饰符(modifier)和通配符(wildcard)模式来表达“所有公共方法”。对帐户的访问,由 pointcut 参数提供。advice使用这个参数,而pointcut则用 this(account) 把它绑定。这样做的效果,就是捕获了正在执行的方法所隶属的Account对象。否则,advice的主体与方法的主体相似。advice可以包含认证代码,或者就像在这个示例中一样,可以调用其他方法。

AspectJ 基于注解的AOP 实现

/*上例中接口和实现类不变*/
/*自定义java类,使用@Aspect 注解表示这是一个切面类*/
@Aspect
public class MyAspect {
     /*在切面类中,为每一个方法指定切入点*/
    @Before(value="execution(* com.xiehe.dao11.IService.doSome(..))")
    public void beforeSome(){
        System.out.println("前置增强!");
    }
    @AfterReturning("execution(* com.xiehe.dao11.IService.doSome(..))")
    public void afterReturn(){
        System.out.println("后置增强!");
    }
}
/*spring配置文件*/
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
        <!-- bean definitions here -->
        <!-- 配置目标bean -->
        <bean id="myService" class="com.xiehe.dao11.ServiceImpl"/>
        <!-- 配置切面 -->
        <bean id="myAspect" class="com.xiehe.dao11.MyAspect"/>
        <!-- 配置aspectj自动代理 -->
        <aop:aspectj-autoproxy/>
</beans>

AspectJ 基于xml的AOP 实现

/*在定义类中,不在需要指定切点和切面注解*/
public class MyAspect {

    public void beforeSome(JoinPoint jp){
        System.out.println("前置增强!");
    }
    public void afterReturn(Object result){
        System.out.println("后置增强 执行结果:" +result);
    }
    public Object around(ProceedingJoinPoint pjp) throws Throwable{
        System.out.println("换绕前:");
        Object result =pjp.proceed();
        System.out.println("环绕后:");
        return result;
    }
    public void afterThrows(Throwable ex){
        System.out.println("异常通知:"+ex.getMessage());
    }
    public void after(){
        System.out.println("最终方法!");
    }
    public void myAspect(){}
}
/*Spring配置文件:applicationSpring.xml*/
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
        <!-- bean definitions here -->
        <!-- 配置目标bean -->
        <bean id="myService" class="com.xiehe.dao13.ServiceImpl"/>
        <!-- 配置切面 -->
        <bean id="myAspect" class="com.xiehe.dao13.MyAspect"/>
       <!-- 配置AOP -->
       <aop:config>
           <!-- 定义切入点 -->
           <aop:pointcut expression="execution(* *..IService.doSome(..))" id="doSomePointcut"/>
           <aop:pointcut expression="execution(* com.xiehe.dao13.IService.doOther(..))" id="doOtherPointcut"/>
           <aop:pointcut expression="execution(* com.xiehe.dao13.IService.doThrid(..))" id="doThridPointcut"/>
           <!-- 定义切面 -->
           <aop:aspect ref="myAspect">
               <aop:before method="beforeSome" pointcut-ref="doSomePointcut"/>
               <aop:after-returning method="afterReturn" pointcut-ref="doOtherPointcut" returning="result"/>
               <aop:around method="around(org.aspectj.lang.ProceedingJoinPoint)" pointcut-ref="doThridPointcut"/>
           </aop:aspect>
       </aop:config>
</beans>
时间: 2024-10-17 12:50:42

AOP:面向切面的相关文章

Javascript aop(面向切面编程)之around(环绕)

Aop又叫面向切面编程,其中“通知”是切面的具体实现,分为before(前置通知).after(后置通知).around(环绕通知),用过spring的同学肯定对它非常熟悉,而在js中,AOP是一个被严重忽视的技术点.但是利用aop可以有效的改善js代码逻辑,比如前端框架dojo和yui3中AOP则被提升至自定义事件的一种内在机制,在源码中随处可见.得益于这种抽象使得dojo的自定义事件异常强大和灵活.dojo中aop的实现在dojo/aspect模块中,主要有三个方法:before.after

sprint.net(2) AOP面向切面编程,spring.net的环绕通知;Spring.net的AOP通知的四种类型

AOP 有点类似于我们MVC里面的Filter过滤器,例如在MVC里面,如果给一个Action上打一个标签,就可以在这个Action执行之前或者之后,额外的执行一个方法,这个就相当于是面向切面编程. 无侵入式的. (也就是在不改变原来的代码的情况下,来跳转到一个其他的方法,执行完毕后回到主方法..),但是spring.net的AOP更牛叉,只需要在xml里面配置,就可以了,不需要在方法上面打特性的标签,也不需要继承什么类(例如MVC的过滤器是继承了ActionFilterAttribute) 主

AOP:面向切面编程

AOP:面向切面编程(Aspect-Oriented Programming)      AOP可以说是对OOP的补充和完善.OOP引入封装.继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合.当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力.也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系.例如日志功能.日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系.在OOP设计中,它导致了大量代码的重复,而不利于各个模块的

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

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

spring入门-AOP 面向切面编程

AOP 面向切面编程 在日常开发中最后将业务逻辑定义在一个专门的service包下,而实现定义在service包下的impl包中, 服务接口以IXXXService形式,而服务实现就是XXXService,这就是规约设计 步骤: 1.E:\Users\WorkSpaces\KmwalletApp\spring\aop\test\HelloWorldService.java 继承(implements)xx接口 2.E:\Users\WorkSpaces\KmwalletApp\spring\ao

Aspects– iOS的AOP面向切面编程的库

简介 一个简洁高效的用于使iOS支持AOP面向切面编程的库.它可以帮助你在不改变一个类或类实例的代码的前提下,有效更改类的行为.比iOS传统的 AOP方法,更加简单高效.支持在方法执行的前/后或替代原方法执行.曾经是 PSPDFKit 的一部分,PSPDFKit,在Dropbox和Evernote中都有应用,现在单独单独开源出来给大家使用. 项目主页: Aspects 最新实例:点击下载 注: AOP是一种完全不同于OOP的设计模式.更多信息,可以参考这里: AOP 百度百科 快速入门 环境要求

java aop面向切面编程

最近一直在学java的spring boot,一直没有弄明白aop面向切面编程是什么意思.看到一篇文章写得很清楚,终于弄明白了,原来跟python的装饰器一样的效果.http://www.cnblogs.com/yanbincn/archive/2012/06/01/2530377.html Aspect Oriented Programming  面向切面编程.解耦是程序员编码开发过程中一直追求的.AOP也是为了解耦所诞生. 具体思想是:定义一个切面,在切面的纵向定义处理方法,处理完成之后,回

Spring:AOP, 面向切面编程

AOP概述 什么是AOP, 面向切面编程 AOP为Aspect Oriented Programming的缩写, 意为:面向切面编程, 通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. AOP是OOP的延续, 是函数式编程的一种衍生范型. 利用AOP可以对业务逻辑的各个部分进行隔离, 从而使得业务逻辑各部分之间的耦合度降低, 提高程序的可重用性, 同时提高了开发的效率. - 传统开发模型: 纵向的编程.  面向切面编程: 纵横配合的编程. AOP的作用及优势 作用: 在程序运行期

Autofac的AOP面向切面编程研究

*:first-child { margin-top: 0 !important; } .markdown-body>*:last-child { margin-bottom: 0 !important; } .markdown-body a:not([href]) { color: inherit; text-decoration: none; } .markdown-body .anchor { float: left; padding-right: 4px; margin-left: -2