AOP初级

来源:互联网 发布:mac腾讯助手官方下载 编辑:程序博客网 时间:2024/05/18 04:00

AOP (Aspect Oriented Programming)即面向切面的编程

aop主要用于身份认证,声明事务等服务。
主要目的是针对业务处理过程中的切面进行提取。它所面对的是处理过程中的某个步骤或阶段,以获得逻辑上的低耦合

AOP和OOP之间的关系:
AOP是OOP的一种,是对OOP的一种完善
解耦性增强 ,程序的可扩展性增强,独立性增强,复用性增强。

关注点分类:
核心关注点(纵切)“ 关注系统的业务逻辑
横切关注点:主要关注系统级的服务,供业务逻辑的使用

业务逻辑用OO技术实现;
切关注点用AOP技术来实现,比如日志,过滤器,监听器 ,对大部分应用可见。

接下来介绍AOP中的基本概念和术语

切面:业务功能模块的实现
切面就是一个抽象出来的功能模块的实现,例如用户登录的功能,可以把这个功能从系统中抽象出来,用一个独立的模块描述,这个独立的模块就是切面。当然这个模块和普通的Java功能模块是有所不同的,它是遵循AOP规范的特殊模块。
通过切面可以把系统中不同层面的问题隔离出来,实现统一的管理,各个切面只需要专注于各自的逻辑实现,而且使用切面还可以降低系统的耦合度,从而大大增强了代码的可重用性。

连接点:程序运行过程中的某个调用过程
连接点即程序运行过程中的某个阶段的,可以是方法调用、异常抛出等。在这些阶段点可以引入切面,从而给系统增加新的服务功能

*通知:切面功能的具体实现
通知即在某个连接点所采用的处理逻辑,即切面功能的实际实现。通知的类型包括Before、After、Around、Throw4种。

切入点:连接点的集合,指明通知何时被触发
切入点即一系列连接点的集合,它指明通知将在何时被触发。切入点可以是指定的类名,也可以是匹配类名和方法名的正则表达式。当匹配的类或方法被调用的时候,就会在这个匹配的地方应用通知。

目标对象:被通知的对象
目标对象就是被通知的对象。在AOP中,目标对象可以专心实现自身的业务逻辑,通知的功能可以在程序运行期间自动引入。

代理:在目标对象通知后创建的新对象
代理对象拥有原目标对象所拥有的一切功能,还包括了通知提供的附加功能。提高了效率;

Advice包括Aspect的真正逻辑,在Java中具体来说就是一个类.
Spring中的Advice包括:

org.springframework.aop. MethodBeforeAdviceorg.springframework.aop. AfterReturningAdvice org.aopalliance.intercept.MethodInterceptororg.springframework.aop.ThrowsAdvice 

前置通知

import java.lang.reflect.Method;import org.springframework.aop.MethodBeforeAdvice;public class 前置通知  implements MethodBeforeAdvice{    //三个参数 一次是调用的方法、在方法中传来的参数、代理的目标对象    public void before(Method arg0, Object[] arg1, Object arg2)            throws Throwable {        System.out.println("这里 是前置监听");         }

后置通知

import java.lang.reflect.Method;import org.springframework.aop.AfterReturningAdvice;public class 后置通知 implements AfterReturningAdvice{     //第一个参数为空,其他参数同前置    public void afterReturning(Object arg0, Method arg1, Object[] arg2,Object arg3) throws Throwable {           System.out.println("这里是后置通知");           }}

两者皆有

import org.aopalliance.intercept.MethodInterceptor;import org.aopalliance.intercept.MethodInvocation;public class In implements MethodInterceptor {    private Integer id;    public Object invoke(MethodInvocation m) throws Throwable {       //前置        System.out.println("我在运行了" + id);        Object o =m.proceed();  //放行       //后置        System.out.println("我任然在运行"+id);        return o;    }   //get()、set()方法}

异常通知

import org.springframework.aop.ThrowsAdvice;//实现了ThrowsAdvice后要自己手写afterThrowing()方法 public class Ex implements ThrowsAdvice{     public void afterThrowing(Exception e){         System.out.println("发生了一个异常");         System.out.println(e.getMessage());     }  }

*注意: 当异常通知所监听的地方直接catch了异常,那么就不再进入监听中
如果只是throw出异常,仍然进入异常通知监听中

在application.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"    xsi:schemaLocation="http://www.springframework.org/schema/beans       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">   <!-- 代理的目标对象 -->    <bean id="cus" class="com.yyy.aop.bean.Customer">        <property name="cusName">            <value>张宏伟</value>        </property>    </bean>   <!--代理的通知名-->    <bean id="after" class="com.yyy.iop.advice.After"></bean>       <!-- 代理对象 代理的全类名是固定的-->    <bean id="customer" class="org.springframework.aop.framework.ProxyFactoryBean">       <!-- 通知的名称 -->        <property name="interceptorNames">            <list>                <value>after</value>            </list>        </property>    <!-- 代理的目标对象 -->        <property name="target">            <ref bean="cus" />        </property>    </bean></beans>

验证监听方法名:

    <bean id="after" class="com.yyy.aop.match.后置监听"></bean>    <bean id="before" class="com.yyy.aop.match.前置通知"></bean><!--class中跟的全类名是监听方法的   固定的--><bean name="advice1"        class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">        <!--跟所监听的方法名-->        <property name="mappedNames">            <list>                <!--a()方法-->                <value>a</value>                <value>b</value>            </list>        </property>        <!--这是指定所使用的通知-->        <property name="advice">            <ref bean="after"></ref>        </property>    </bean>

*注意:代理监听的是目标对象中的方法,而不是目标对象本身

正则表达验证:

    <bean id="after" class="com.yyy.aop.match.后置监听"></bean>    <bean id="before" class="com.yyy.aop.match.前置通知"></bean>    <bean name="advice2"        class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">        <!--跟正则表达式的的规则-->        <property name="patterns">            <list>                <value>.*User.*</value>            </list>        </property>        <property name="advice">            <ref bean="after" />        </property>    </bean>

正则中:
. 符合任何的单一字符
+符合前一个字符一次或者多次 不能再验证的开头
*符合前一个字符0次或者多次 不能再验证的开头

注意:使用监听方法和正则验证的时候,在代理对象的 interceptorNames属性中,不再跟目标对象的名称,而是跟两种验证的id。

    <bean id="ccc" class="org.springframework.aop.framework.ProxyFactoryBean">        <property name="interceptorNames">        <!--调用了正则时候这里跟的不是目标对象的id了,而是正则的监听id-->            <list>                <value>advice2</value>            </list>        </property>        <property name="target">            <ref bean="mubiao" />        </property>    </bean>

总的来说 正则和对方法的监听,都是将前置或者后置方法,装配到其中,然后再做其他操作

0 0
原创粉丝点击