`
senton
  • 浏览: 205804 次
  • 性别: Icon_minigender_1
  • 来自: 紫禁城
社区版块
存档分类
最新评论

Spring中创建切面

阅读更多


一。创建切面:
Spring中的通知类型有四种:
Around:拦截对目标对象方法调用,
Before:在目标方法被调用之前调用,
After:在目标方法被调用之后调用,
Throws:当目标方法抛出异常时调用。

1)下面是一个Before类型的简单例子。
1.首先创建一个拦截的类:
package cn.itcast;

import java.lang.reflect.Method;
import java.util.Arrays;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.MethodBeforeAdvice;

public class MyMethodBeforeAdvice implements MethodBeforeAdvice {//实现MethodBeforeAdvice接口

 Log log = LogFactory.getLog(this.getClass());

 public MyMethodBeforeAdvice() {
  super();
 }

 public void before(Method arg0, Object[] arg1, Object arg2)//实现MethodBeforeAdvice接口的before方法,
   throws Throwable {
  StringBuilder sb = new StringBuilder();
  if (arg1 == null) {
   sb = new StringBuilder("无参数!");
  } else {
   for (int i = 0; i < arg1.length; i++) {
    if (i != arg1.length - 1) {
     sb.append(arg1[i] + ",");
    } else {
     sb.append(arg1[i]);
    }
   }
  }
  log.info("类名: " + arg2.getClass().getName() + "   方法名: "
    + arg0.getName() + "   参数:" + sb.toString());
 }

}

这个类中我们没做太多的事,就是把方法名等信息打印出来而已,当然你可以根据业务需求做其他的很多事情。

2.
写一个配置文件: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="myArrayList" class="java.util.ArrayList" />
 <bean id="myMethodBeforeAdvice" class="cn.itcast.MyMethodBeforeAdvice" />

 <bean id="collection" class="org.springframework.aop.framework.ProxyFactoryBean">
  <property name="interceptorNames">
   <!--指定拦截类的名字,可以加入多个,它会去检查此类实现的是什么接口,然后去调用里面相应的方法-->
   <list>
    <value>myMethodBeforeAdvice</value>
   </list>
  </property>
  <property name="target"><!--指定目标对象-->
   <ref bean="myArrayList" />
  </property>
  <property name="proxyInterfaces">
   <!--指定目标对象实现的接口,也可以是多个-->
   <list>
    <value>java.util.Collection</value>
   </list>
  </property>
 </bean>

</beans>

3.再写一个测试类
package cn.itcast.test;

import java.util.Collection;
import junit.framework.TestCase;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestMySpringAop extends TestCase {

 ApplicationContext applicationContext = null;

 Collection collection = null;

 protected void setUp() throws Exception {
  super.setUp();
  applicationContext = new ClassPathXmlApplicationContext(
    "applicationContext.xml");
 }

 public void testMySpring() {
  collection = (Collection) applicationContext.getBean("collection");
  collection.add("zhangsan");
  assertEquals(1, collection.size());
 }
}

运行!结果为:
类名: java.util.ArrayList   方法名: add   参数:zhangsan
类名: java.util.ArrayList   方法名: size   参数:无参数!

看....简单吧?!

2) 再来一个After的例子。
1.首先创建一个拦截的类:
package cn.itcast;

import java.lang.reflect.Method;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.AfterReturningAdvice;

public class MyAfterReturningAdvice implements AfterReturningAdvice {

 Log log = LogFactory.getLog(this.getClass());

 public MyAfterReturningAdvice() {
  super();
 }

 public void afterReturning(Object arg0, Method arg1, Object[] arg2,
   Object arg3) throws Throwable {

  StringBuilder sb = new StringBuilder();
  if (arg2 == null) {
   sb = new StringBuilder("无参数!");
  } else {
   for (int i = 0; i < arg2.length; i++) {
    if (i != arg2.length - 1) {
     sb.append(arg2[i] + ",");
    } else {
     sb.append(arg2[i]);
    }
   }
  }

  log.info("返回值: " + arg0.toString() + "    类名: "
    + arg3.getClass().getName() + "   方法名: " + arg1.getName()
    + "   参数:" + sb.toString());
 }

}

2.把上面的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="myArrayList" class="java.util.ArrayList" />
 <bean id="myAfterReturningAdvice" class="cn.itcast.MyAfterReturningAdvice" />

 <bean id="collection" class="org.springframework.aop.framework.ProxyFactoryBean">
  <property name="interceptorNames">
   <value>myAfterReturningAdvice</value>
  </property>
  <property name="target">
   <ref bean="myArrayList" />
  </property>
  <property name="proxyInterfaces">
   <value>java.util.Collection</value>
  </property>
 </bean>

</beans>

3.测试类依然用上面那个。

运行!结果为:
返回值的类型: true    类名: java.util.ArrayList   方法名: add   参数:zhangsan
返回值的类型: 1    类名: java.util.ArrayList   方法名: size   参数:无参数!

看......现在返回值也取出来了......... 

3) 再来看一个Around的例子。步骤和上面一样,
1.首先也是创建一个拦截的类:

package cn.itcast;

import java.lang.reflect.Method;
import java.util.ArrayList;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class MyMethodInterceptor implements MethodInterceptor {

 public MyMethodInterceptor() {
  super();
 }

 Log log = LogFactory.getLog(this.getClass());

 public Object invoke(MethodInvocation arg0) throws Throwable {
  Object[] arguments = arg0.getArguments();
  Method method = arg0.getMethod();
  Object objName = arg0.getThis();
  StringBuilder sb = new StringBuilder();
  if (arguments == null) {
   sb = new StringBuilder("无参数!");
  } else {
   for (int i = 0; i < arguments.length; i++) {
    if (i != arguments.length - 1) {
     sb.append(arguments[i] + ",");
    } else {
     sb.append(arguments[i]);
    }
   }
  }
  //在调用目标方法之前做的事
  log.info("类名: " + objName.getClass().getName() + "   方法名: " + method.getName()
    + "   参数:" + sb.toString());
  
  Object object = arg0.proceed();//通过调用此方法来调用目标方法。
  
  //在调用目标方法之后做的事
  if(objName instanceof ArrayList){
   ArrayList arrayList = (ArrayList) objName;
   arrayList.add("lisi");
   arrayList.add("wangwu");
   log.info("size = " + arrayList.size());
  }
  return object;
 }
}

2.把上面的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="myArrayList" class="java.util.ArrayList" />
 <bean id="myMethodInterceptor" class="cn.itcast.MyMethodInterceptor" />

 <bean id="collection" class="org.springframework.aop.framework.ProxyFactoryBean">
  <property name="interceptorNames">
   <value>myMethodInterceptor</value>
  </property>
  <property name="target">
   <ref bean="myArrayList" />
  </property>
  <property name="proxyInterfaces">
   <value>java.util.Collection</value>
  </property>
 </bean>

</beans>

3.运行!结果:
类名: java.util.ArrayList   方法名: add   参数:zhangsan
size = 3
类名: java.util.ArrayList   方法名: size   参数:无参数!
size = 5

我们类分析一下运行的结果。在测试类中调用了一次目标类的add方法,此时size为1,然后在拦截类里面把对象取出来调用了两次add方法,这时size为3,也就是我们看到的第一个size,接着在测试类中调用了一次size方法,此时它又被拦截了,所以再一次调用了两个add方法,最后的size当然就是5了。当然如果我们这里用的是Set集合就不会再add后面的两个已存在的对象了。

4)一个ThrowsAdvice的例子。步骤和上面一样,
1.写一个拦截异常的类。这里面可以有多个带不同异常参数类型afterThrowing方法,运行时根据抛出异常的类型去调用恰当的方法,

package cn.itcast;

import java.lang.reflect.Method;
import org.springframework.aop.ThrowsAdvice;
public class MyThrowsAdvice implements ThrowsAdvice {

 public MyThrowsAdvice() {
  super();
  // TODO Auto-generated constructor stub
 }

 public void afterThrowing(Method method, Object[] args, Object target,
   NullPointerException npe) {
  System.out.println("调用 " + target.getClass().getName() + " 的 "
    + method.getName() + " 方法时发生了 " + npe.getClass().getName()
    + " 异常!");
 }
}


2.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="myArrayList" class="java.util.ArrayList" />
 <bean id="myMethodBeforeAdvice" class="cn.itcast.MyMethodBeforeAdvice" />
 <bean id="myAfterReturningAdvice" class="cn.itcast.MyAfterReturningAdvice" />
 <bean id="myMethodInterceptor" class="cn.itcast.MyMethodInterceptor" />
 <bean id="myThrowsAdvice" class="cn.itcast.MyThrowsAdvice" />

 <bean id="collection" class="org.springframework.aop.framework.ProxyFactoryBean">
  <property name="interceptorNames">
   <value>myThrowsAdvice</value>
  </property>
  <property name="target">
   <ref bean="myArrayList" />
  </property>
  <property name="proxyInterfaces">
   <value>java.util.Collection</value>
  </property>
 </bean>

</beans>

3.写一个main方法来测试一下:
package cn.itcast;

import java.util.Collection;

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

public class MainClass {

 public MainClass() {
  super();
 }

 public static void main(String[] args) {
  // TODO Auto-generated method stub
  ApplicationContext applicationContext = null;

  Collection collection = null;

  applicationContext = new ClassPathXmlApplicationContext(
    "applicationContext.xml");
  collection = (Collection) applicationContext.getBean("collection");
  collection.add("zhangsan");
  Object[] object = null;
  collection.toArray(object);//故意来抛出一个异常试试看
 }
}


来看看运行结果:

调用 java.util.ArrayList 的 toArray 方法时发生了 java.lang.NullPointerException 异常!
Exception in thread "main" java.lang.NullPointerException
 at java.util.ArrayList.toArray(Unknown Source)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
 at java.lang.reflect.Method.invoke(Unknown Source)
 at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:335)
 at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:181)
 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:148)
 at org.springframework.aop.framework.adapter.ThrowsAdviceInterceptor.invoke(ThrowsAdviceInterceptor.java:118)
 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
 at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:176)
 at $Proxy0.toArray(Unknown Source)
 at cn.itcast.MainClass.main(MainClass.java:29)

看到了吗?我们在拦截异常类里面的打印语句出来了:
调用 java.util.ArrayList 的 toArray 方法时发生了 java.lang.NullPointerException 异常!

当然在这里你还可以做很多事情。在本程序里面仅打印出这条简单的信息而已。
下面的是系统抛出的。由此可以看出,如果有异常的话,代理对象捕获异常并且调用合适的ThrowsAdvice方法。ThrowsAdvice被执行后,原来的异常继续被抛出,并且象其他异常一样被传播出去。
 

分享到:
评论

相关推荐

    spring aop 自定义切面示例

    下面我们将详细探讨如何在Spring中创建和使用自定义切面,以及AspectJ的相关知识。 首先,让我们理解什么是切面。在AOP中,切面是跨越多个对象的行为或关注点的模块化,例如日志记录、事务管理、性能监控等。自定义...

    Spring AOP面向切面三种实现

    在IT行业中,Spring框架是Java企业级应用开发的首选,其强大的功能之一就是AOP(面向切面编程)。本文将详细解析Spring AOP的三种实现方式,帮助你深入理解这一重要概念。 首先,理解AOP的基本概念至关重要。AOP是...

    Spring自定义切面事务问题

    - 为了确保自定义切面中的事务能够正常工作,我们需要注意事务管理器切面与其他自定义切面之间的`order`属性设置。 - 对于一般的业务逻辑来说,将事务管理器的`order`值设置得稍微高一点(例如200),而自定义切...

    spring自定义切面实例

    通过利用Spring的AOP(面向切面编程)特性,特别是@AspectJ注解的支持,我们可以创建灵活、可重用的业务逻辑切面,从而在不修改现有代码的情况下,对应用程序的行为进行增强。 ### Spring自定义切面的核心概念 ###...

    spring的aop切面编程实例

    3. **配置XML**: 在Spring的配置文件(如`applicationContext.xml`)中,你需要启用AOP代理并声明切面。首先,启用AOP上下文: ```xml ``` 然后,声明切面,指定其类和通知: ```xml (* ...

    spring切面小例子

    在Spring框架中,AOP(面向切面编程)是一种强大的设计模式,它允许开发者将关注点从核心业务逻辑中分离出来,例如日志记录、事务管理、性能监控等。本示例将深入探讨如何在Spring中实现AOP,特别是通过注解的方式。...

    Spring面向切面编程AOP

    面向切面编程(AOP,Aspect Oriented Programming)是Spring框架中的一个重要特性,它提供了一种模块化和声明式的方式来处理程序中的横切关注点,如日志、事务管理、安全控制等。AOP的核心概念包括切面、通知、连接...

    Spring AOP 建立一个简单的切面及测试

    创建切面** 创建`Audience`类作为切面类,即观众类。通过`@Aspect`注解将其定义为切面,并使用`@Around`注解指定`watchPerformance()`方法作为`perform()`切点的环绕通知。 ```java @Aspect public class ...

    spring切面AOP所使用的jar包

    Spring框架的AOP(面向切面编程)是其核心特性之一,它允许开发者在不修改原有代码的情况下,通过切面来插入额外的功能,比如日志记录、事务管理、性能监控等。在Spring AOP中,主要涉及到两个重要的库:...

    spring AOP切面编程

    在Spring中,AOP通过代理机制实现了切面编程,允许我们在不修改原有业务代码的情况下,插入额外的功能。 一、理解AOP概念 1. 切面(Aspect):AOP的核心概念,代表一个关注点的模块化,这个关注点可能会横切多个...

    Spring Boot Aspect 切面 AOP 拦截器 Interceptor 监控control请求耗时

    在Spring Boot应用中,面向切面编程(AOP)是一种强大的设计模式,它允许我们以声明式的方式插入代码,比如日志记录、事务管理或权限检查。Aspect是AOP的核心概念,它封装了关注点,使得我们可以将这些关注点与业务...

    Spring Aop面向切面的java代码

    Spring AOP,全称Spring面向切面编程,是Spring框架中的一个重要组成部分,它提供了一种在不修改原有代码的情况下,对程序进行功能增强的技术。面向切面编程(Aspect Oriented Programming,AOP)的核心思想是将关注...

    spring使用动态代理面向切面编程(AOP) xml

    在Spring框架中,面向切面编程(AOP)是一种强大的设计模式,它允许开发者将关注点分离,将横切关注点(如日志、事务管理、权限检查等)与核心业务逻辑解耦。本篇文章将深入探讨如何使用Spring的动态代理机制实现AOP...

    AOP_使用spring框架进行面向切面编程

    Spring框架是Java领域中实现AOP的常用工具,它通过提供声明式的方式来实现切面编程,使开发者能够更专注于业务逻辑。 在Spring框架中,AOP主要通过以下几个核心概念来实现: 1. **切面(Aspect)**:切面是关注点...

    spring 切面编程实例

    6. **代理(Proxy)**:Spring AOP通过创建代理对象来实现切面功能。有JDK动态代理和CGLIB代理两种方式。如果目标类实现了接口,Spring会使用JDK动态代理;如果没有,Spring会使用CGLIB生成一个子类来作为代理。 在...

    Spring mvc mybatis plus 实现AOP 切面日志系统

    在IT行业中,Spring MVC、MyBatis Plus以及AOP(面向切面编程)是Java Web开发中的重要组件,常用于构建高效、灵活的企业级应用。本项目“Spring MVC Mybatis Plus 实现AOP 切面日志系统”旨在提供一个基础的日志...

    day39-Spring 06-Spring的AOP:带有切点的切面

    在Spring框架中,AOP(Aspect Oriented Programming,面向切面编程)是一种强大的设计模式,它允许程序员将关注点从核心业务逻辑中分离出来,如日志、事务管理等。在"day39-Spring 06-Spring的AOP:带有切点的切面...

    struts2+spring+hibernate分页,事务,自定义切面

    Struts2、Spring和Hibernate是Java Web开发中的三大框架,它们各自负责不同的职责:Struts2主要用于MVC(模型-视图-控制器)架构的实现,Spring提供了强大的依赖注入和面向切面编程功能,而Hibernate则是一个优秀的...

    第十四章 Spring4 切面事物与事物通知与传播行为

    在IT领域,Spring框架是Java开发中的核心组件之一,它为开发者提供了许多强大的功能,包括依赖注入、面向切面编程(AOP)以及事务管理。本章将详细探讨Spring4中的切面事务处理、事物通知以及传播行为。 一、切面...

    mybatis 拦截器 + spring aop切面 + spring事务+ 反射工具类

    Spring AOP是Spring框架的一个重要特性,它实现了面向切面编程,允许开发者定义“切面”,即关注点的模块化,比如日志记录、性能监控、安全控制等。切面通过通知(advises)来增强其他对象的行为。Spring支持多种...

Global site tag (gtag.js) - Google Analytics