AOP专业术语基本概念:(网上大把多的解释,有的很容易理解,有的却是很迷糊,小弟的理解不知道是否是容易理解的那类,请各位指正)

AOP为Aspect Oriented Programming的缩写,意为:面向切面编程。

切面(Aspect):就是一个关注点的模块化,比如说记录日志,这个肯定需要一个具体的方法来实现,而且这个方法需要一个类来存放,这个类就是切面。

通知(Advice):关注点的具体实现,也就是记录日志的具体实现方法,spring AOP专业术语称为advice。

连接点(Joinpoint):在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候需要记录日志。在Spring AOP中,一个连接点总是表示一个方法的执行。

通知类型根据链接点的位置来分有(帮助手册的定义):

前置通知(Before advice):在某连接点之前执行的通知,但这个通知不能阻止连接点之前的执行流程(除非它抛出一个异常)。 

后置通知(After returning advice):在某连接点正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回。 

异常通知(After throwing advice):在方法抛出异常退出时执行的通知。 

最终通知(After (finally) advice):当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。 

环绕通知(Around Advice):包围一个连接点的通知,如方法调用。这是最强大的一种通知类型。环绕通知可以在方法调用前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它自己的返回值或抛出异常来结束执行。 

?

切入点(Pointcut):匹配连接点的动作。就是把通知和一个切入点表达式关联,并在满足这个切入点的连接点上运行(例如在执行修改用户信息之后需要记录日志修改前和修改后的内容)。切入点表达式如何和连接点匹配是AOP的核心:Spring缺省使用AspectJ切入点语法。 

AspectJ切入点表达式如下:

// pointcut 表达式,execution切入点主要的指示符,还有within ,target 等等

@Pointcut("execution(* transfer(..))") 

private void anyOldTransfer(){} // the pointcut 的标识,而不是方法调用

 


目标对象(Target Object): 被一个或者多个切面所通知的对象。也被称做被通知(advised)对象。 既然Spring AOP是通过运行时代理实现的,这个对象永远是一个被代理(proxied)对象。 

 

AOP代理(AOP Proxy)AOP代理(AOP Proxy):AOP框架创建的对象,用来实现切面契约(例如通知方法执行等等)。在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。

 

织入(Weaving):把通知应用到目标对象上的过程叫织入。

 

使用注解(annotation)实现AOP:

首先注解需要用到的包:

aspcetjrt.jar和aspectjweaver.jar  

同时为了使配置文件支持aop标签,必须在<beans>里加入如下内容

<beans 

  xmlns:aop="http://www.springframework.org/schema/aop"

xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">

 

依据概念可以知道切面就是一个java类,类中有具体实现advice的方法。

对该类进行注解@Aspect

 

package spring.proxy;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class SpringAop
{


 @Pointcut("execution(* *(..))") 
 private void allMethod(){}


 //新增处理功能,Advice
 @Before("allMethod()")//该advice通过该标识找到切入点的注解,该注解明确了advice在哪个连接点执行和执行的位置
 public void checkMethod()
 {
  System.out.println("checkMethod-------");
 }

}

 

接口

package spring.proxy;

public interface UserManager
{

 public String getUser(int userID);

 public void delUser(int userID);

 public void modifyUser(String userID,String password);
}

 

接口实现类:

package spring.proxy;

public class UserManagerImpl implements UserManager
{

 @Override
 public void delUser(int userID)
 {
  System.out.println("delUser------");
 }

 @Override
 public String getUser(int userID)
 {
  System.out.println("getUser------");
  return ""+userID;
 }

 @Override
 public void modifyUser(String userID, String password)
 {
  System.out.println("modifyUser------");
 }

}

 

现在需要在接口实现类UserManagerImpl 的各个方法之前加上一个检查方法,那么这时候就可以使用spring AOP来实现。

SpringAop类就是一个切面,也就是advice的模块化,advice的具体实现放在该类中。

最后需要在配置文件里做相应的配置

 

<?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-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">

<!-- 该配置使得java代码中的spring注解生效 -->

        <aop:aspectj-autoproxy/>
<!--配置实现类-->
      <bean id="userManagerimpl" class="spring.proxy.UserManagerImpl"/>
<!--配置切面类-->
      <bean id="SpringAop" class="spring.proxy.SpringAop"/>
</beans>

 

在测试类中调用实现类的方法,即可实现在调用该方法之前进行检查

 

package spring.proxy;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Client
{

 public static void main(String[] args)
 {
  BeanFactory factory = new ClassPathXmlApplicationContext("beans.xml"); 

  UserManager user = (UserManager) factory.getBean("userManagerimpl");

  user.getUser(1);
 }

}

 

测试结果:

checkMethod-------
getUser------