Spring AOP(创建切面理解)1

89 篇文章 0 订阅
21 篇文章 0 订阅

AOP:一个系统,包括很多业务对象.拿一个简单的学生系统作为例子.学生系统需要包括学生服务,课程服务,内容服务等等.而且,几乎每个服务都需要一些公共的模块.比如日志模块,安全模块,事务服务器等等.问题就出来了,我们是在每个业务对象里面都添加这些模块么?我想这样的话不管是复杂度还有测试方面考虑,你都不愿意这么干!就这样,AOP就是解决这个问题的.至于怎么解决,看下面!

1几个AOP术语(下面的术语是这章要用到的几个概念,这些概念是从<<spring in action>>里面解释的)

通知:别看这个鸟名字,一点实际含义都没的.通知的真正意思是那些公共模块的实现(比如说日志的实现:将日志写入日志文件).下面的例子当中就有三种通知.前,后,环绕.(看不懂,那就看下面!)

目标对象 这个容易理解些.就是你的通知要加入的地方.比如你要在学生服务这个业务对象里面添加一个通知(通知的含义见上面.~~).那这个学生服务就是一个目标对象..

代理 这里之所以说城代理的原因是,spring在实现这个功能的时候使用的是jdk的动态代理.通俗点说,代理就是目标对象+通知!当然,代理是通过配置文件组装的(如果不是这样,那要AOP干嘛).当然,也可以使用其他方式来组装.这样说可能不够严谨.换种说法就是.目标对象是应用AOP前的对象.代理对象就是应用AOP后的对象..而且对于客户对象来说,两个是一样的.不会因为目标对象加了代理而改变

2通知

spring支持的通知有四类.前置通知,后置通知,环绕通知和异常通知.具体懒得解释了.重点的我在下面例子上面写

例子:

目标对象接口(反正都要用接口的,别问为什么.要不就别用spring)

package com.service;

public interface Student {
void addStudent(String s);
}
目标对象实现

package com.serviceimpl;
import com.service.*;
public class StudentImpl implements Student{
  public void addStudent(String s){
   System.out.println("欢迎你,"+s+"!");//够简单了吧
  }
}
前置通知

package com.advice;
import java.lang.reflect.*;//这里其实是import  java.lang.reflect.Method;  
import org.springframework.aop.MethodBeforeAdvice;

public class BeforeAdvice implements MethodBeforeAdvice {//前置通知就是实现这个接口
 public void before (Method method,Object[] args,Object object)throws Throwable{//覆盖这个方法.对应的三个参数分别是方法,参数列表,目标对象
  String color=#ff0000>//获取参数.args[0]表示第一个参数
  System.out.println("这是beforeAdvice类所带的before方法"+name);
 }
}

后置通知

package com.advice;
import java.lang.reflect.*;
import org.springframework.aop.AfterReturningAdvice;

public class AfterAdvice implements AfterReturningAdvice{
   public void afterReturning(Object returnValue,Method method,Object[] arg,Object object) throws Throwable {
    System.out.println("这是AfterAdvice类的afterReturning方法.");//returnValue表示目标方法的返回值.本例子就是addStudent方法的返回值(本例子是void的)
   }
}
环绕通知 
环绕通知与前面两个通知有两个重要区别.一,环绕通知能控制目标方法是否调用(如果要调用,要用MethodInvocation.proceed()方法.二.环绕通知能控制返回的对象(不同于目标方法的返回对象)

前面两种通知的目标方法总是会被调用.除非抛出异常.

package com.advice;
import org.aopalliance.intercept.MethodInterceptor;  
import org.aopalliance.intercept.MethodInvocation;   
 

public class CompareInterceptor implements MethodInterceptor{  
 
      public Object invoke(MethodInvocation invocation) throws Throwable{  
         Object result = null;  
         String stu_name = invocation.getArguments()[0].toString();  
        if ( stu_name.equals("dragon")){  
             //如果学生是dragon时,执行目标方法,  
             result= invocation.proceed();  
               
        } else{  
            System.out.println("此学生是"+stu_name+"而不是dragon,不批准其加入.");  
        }  
         
          return result;  
     }  

配置文件applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
 
 <beans>
 
 <bean id="beforeAdvice" class="com.advice.BeforeAdvice"></bean>
 <bean id="afterAdvice" class="com.advice.AfterAdvice"></bean>
 <bean id="compareInterceptor" class="com.advice.CompareInterceptor"></bean>
 <bean id="studenttarget" class="com.serviceimpl.StudentImpl"></bean>
//目标对象实现类

<bean id="student">//这个就是创建代理Bean
  <property name="proxyInterfaces">
    <value>com.service.Student</value>//目标对象接口类
  </property>
  <property name="interceptorNames">
    <list>
     <value>beforeAdvice</value>//加入几个通知.这个是上面对应的bean id
     <value>afterAdvice</value>
    <value>compareInterceptor</value> 
    </list>
  </property>
  <property name="target">//实现类
    <ref bean="studenttarget"/>
  </property>

</bean>

</beans>

测试类,Test.java

package com.act;

 

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

import com.service.Student;


public class Test {

   public static void main(String[] args) {

      ApplicationContext ctx =
          new FileSystemXmlApplicationContext("/src/applicationContext.xml");//配置文件我放在SRC下
      
      Student person = (Student)ctx.getBean("student");//这里获得的是代理对象的bean
      person.addStudent("dragon");
     
     // person.addStudent("javadragon");
    }

}

运行该程序时,要加上commons-logging.jar 包

<property name="proxyInterfaces">
<property name="interceptorNames">
<property name="target">
这三个属性是一定要配置的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值