第三章 AOP 通过Java API创建增强

3.3.1增强类型

前置增强:org.springframework.aop.MethodBeforeAdvice

后置增强:org.springframework.aop.AfterReturningAdvice

环绕增强:org.aopalliance.intercept.MethodInterceptor

异常抛出增强:org.springframework.aop.ThrowsAdvice

引介增强:org.springframework.aop.support.DelegatingIntroductionInterceptor

3.3.2前置增强

就是在连接点方法执行之前执行的内容。

如:我们在UserDaoImpl的save()方法执行之前执行一些内容。

a、UserDao与UserDaoImpl:

[java] view
plain
copyprint?

  1. public interface UserDao {    
  2.     public void save();    
  3. }    

[html] view
plain
copyprint?

  1. public class UserDaoImpl implements UserDao {    
  2.     public void save() {    
  3.         System.out.println("保存用户...");    
  4.     }    
  5. }    

b、创建一个增强类实现MethodBeforeAdvice接口

public class UserDaoBeforeAdvice implements MethodBeforeAdvice {
	public void before(Method method, Object[] args, Object object)
			throws Throwable {
		System.out.println("我是前置增强");
	}
}

c、配置

<!-- 把增强类交由spring管理 -->
	<bean id="userDaoBeforeAdvice" class="cn.framelife.spring.advice.UserDaoBeforeAdvice"></bean>

	<!-- 把目标类交由spring管理 -->
	<bean id="userDao" class="cn.framelife.spring.dao.impl.UserDaoImpl"></bean>

	<!--
		设置代理类
		p:target-ref 目标对象
		p:proxyInterfaces 代理所要实现的接口,也就是目标对象的接口
		p:interceptorNames 织入的增强Bean,可以是多个,用","号分开
	-->
	<bean id="adviceUserDao"
		class="org.springframework.aop.framework.ProxyFactoryBean"
		p:proxyInterfaces="cn.framelife.spring.dao.UserDao"
		p:interceptorNames="userDaoBeforeAdvice"
		p:target-ref="userDao"
	 />

d、main方法中测试

ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
		//通过代理来获取userDao对象
		UserDao userDao = (UserDao) context.getBean("adviceUserDao");
		userDao.save();

f、结果

我是前置增强
保存用户...

3.3.3后置增强

就是在连接点方法执行之后执行的内容。

a、UserDao与UserDaoImpl:

[java] view
plain
copyprint?

  1. public interface UserDao {    
  2.     public void save();    
  3. }    

[html] view
plain
copyprint?

  1. public class UserDaoImpl implements UserDao {    
  2.     public void save() {    
  3.         System.out.println("保存用户...");    
  4.     }    
  5. }    

b、创建一个增强类实现AfterReturningAdvice接口

public class UserDaoAfterAdvice implements AfterReturningAdvice {
	@Override
	public void afterReturning(Object object, Method method, Object[] args,
			Object arg3) throws Throwable {
		System.out.println("我是后置增强");
	}
}

c、配置

<bean id="userDaoBeforeAdvice" class="cn.framelife.spring.advice.UserDaoBeforeAdvice"></bean>
	<bean id="userDaoAfterAdvice" class="cn.framelife.spring.advice.UserDaoAfterAdvice"></bean>

	<bean id="userDao" class="cn.framelife.spring.dao.impl.UserDaoImpl"></bean>

	<bean id="adviceUserDao"
		class="org.springframework.aop.framework.ProxyFactoryBean"
		p:proxyInterfaces="cn.framelife.spring.dao.UserDao"
		p:interceptorNames="userDaoBeforeAdvice,userDaoAfterAdvice"
		p:target-ref="userDao"
	 />

d、main方法中测试

ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
		//通过代理来获取userDao对象
		UserDao userDao = (UserDao) context.getBean("adviceUserDao");
		userDao.save();

f、结果

保存用户...
我是后置增强

3.3.4环绕增强

环绕增强与struts2的AOP类似。

a、UserDao与UserDaoImpl:

[java] view
plain
copyprint?

  1. public interface UserDao {    
  2.     public void save();    
  3. }    

[html] view
plain
copyprint?

  1. public class UserDaoImpl implements UserDao {    
  2.     public void save() {    
  3.         System.out.println("保存用户...");    
  4.     }    
  5. }    

b、创建一个增强类实现MethodInterceptor接口

public class UserDaoSurroundAdvice implements MethodInterceptor {

	@Override
	public Object invoke(MethodInvocation invocation) throws Throwable {
		System.out.println("环绕增强在方法前执行...");
		Object object = invocation.proceed();
		System.out.println("环绕增强在方法后执行...");
		return object;
	}

}

c、配置

<bean id="userDaoSurroundAdvice" class="cn.framelife.spring.advice.UserDaoSurroundAdvice"></bean>

	<bean id="userDao" class="cn.framelife.spring.dao.impl.UserDaoImpl"></bean>

	<bean id="adviceUserDao"
		class="org.springframework.aop.framework.ProxyFactoryBean"
		p:proxyInterfaces="cn.framelife.spring.dao.UserDao"
		p:interceptorNames=" userDaoSurroundAdvice"
		p:target-ref="userDao"
	 />

d、main方法中测试

ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
		//通过代理来获取userDao对象
		UserDao userDao = (UserDao) context.getBean("adviceUserDao");
		userDao.save();

f、结果

环绕增强在方法前执行...
保存用户...
环绕增强在方法后执行...

3.3.5异常抛出增强

就是在方法出现异常之后执行的代码。

a、UserDao与UserDaoImpl:

[java] view
plain
copyprint?

  1. public interface UserDao {    
  2.     public void save();    
  3. }    
public class UserDaoImpl implements UserDao {    
     public void save() {    
         System.out.println("保存用户...");    
         //使方法在运行的时候抛出一个异常
          throw new RuntimeException("运行时异常...");

    }    
}  

b、创建一个增强类实现ThrowsAdvice接口

public class UserDaoThrowsAdvice implements ThrowsAdvice {
	public void afterThrowing(Method method,Object[] args,Object taglet,Exception ex)throws Throwable{
		System.out.println("我是异常抛出接口");
		System.out.println(method.getName());
		System.out.println(ex.getMessage());
	}
}

c、配置

<bean id="userDaoThrowAdvice" class="cn.framelife.spring.advice.UserDaoThrowsAdvice"></bean>

<!--
	 p:proxyTargetClass="false"
	如果目标对象是一个类,而不是一个接口,我们设置为true
-->
	<bean id="userDao" class="cn.framelife.spring.dao.impl.UserDaoImpl"></bean>

	<bean id="adviceUserDao"
		class="org.springframework.aop.framework.ProxyFactoryBean"
		p:proxyInterfaces="cn.framelife.spring.dao.UserDao"
		p:interceptorNames="userDaoThrowAdvice"
		p:target-ref="userDao"
		p:proxyTargetClass="false"
	 />

d、main方法中测试

ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
		//通过代理来获取userDao对象
		UserDao userDao = (UserDao) context.getBean("adviceUserDao");
		userDao.save();

f、结果

保存用户...
Exception in thread "main" java.lang.RuntimeException: 运行时异常...
	at cn.framelife.spring.dao.impl.UserDaoImpl.save(UserDaoImpl.java:12)
	at cn.framelife.spring.dao.impl.UserDaoImpl$$FastClassByCGLIB$$18bd6dee.invoke(<generated>)
	at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191)
	at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:688)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
	at org.springframework.aop.framework.adapter.ThrowsAdviceInterceptor.invoke(ThrowsAdviceInterceptor.java:124)我是异常抛出接口
save
运行时异常...

	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
	at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:621)
	at cn.framelife.spring.dao.impl.UserDaoImpl$$EnhancerByCGLIB$$5bbe38b0.save(<generated>)
	at cn.framelife.spring.test.Test.main(Test.java:17)

3.3.6引介增强

     引介增强是为目标类创建新的方法和属性,引介增强的连接点是类级别的,不是方法级别的。通过引介增强,我们可以为目标类添加一个接口的实现,即原来目标类未实现某个接口,通过引介增强可以为目标类创建实现某个接口的代理。

a、UserDao与UserDaoImpl:

[java] view
plain
copyprint?

  1. public interface UserDao {    
  2.     public void save();    
  3. }    

[html] view
plain
copyprint?

  1. public class UserDaoImpl implements UserDao {    
  2.     public void save() {    
  3.         System.out.println("保存用户...");    
  4.     }    
  5. }    

b、新建一个接口AInterface

public interface AInterface {
	public void say();
}

c、增强类继承DelegatingIntroductionInterceptor实现AInterface

public class IntroductionAdvice extends DelegatingIntroductionInterceptor implements AInterface {
	/*
	 * 实现AInterface中的方法
	 */
	public void say() {
		System.out.println("UserDao要说话");
	}

	/*
	 * 重写DelegatingIntroductionInterceptor的invoke方法
	 */
	public Object invoke(MethodInvocation mi) throws Throwable {
		System.out.println("方法执行前执行");
		System.out.println(mi.getClass().getName());
		System.out.println(mi.getMethod().getName());
		Object object = super.invoke(mi);
		System.out.println("方法执行后执行");
		return object;
	}
}

d、配置

<bean id="userDao" class="cn.framelife.spring.dao.impl.UserDaoImpl"></bean>

	<bean id="introductionAdvice" class="cn.framelife.spring.advice.IntroductionAdvice"></bean>
	<!--
		代理类设置
		p:proxyTargetClass="true" 引介增强一定要通过创建子类来生成代理,所以要设置为true。
			也不需要配置p:proxyInterfaces目标类的接口
		p:interfaces 引介增强所实现的接口
	 -->
	<bean id="aProxy"
		class="org.springframework.aop.framework.ProxyFactoryBean"
		p:interfaces="cn.framelife.spring.dao.AInterface"
		p:interceptorNames="introductionAdvice"
		p:target-ref="userDao"
		p:proxyTargetClass="true" />

e、main方法中测试

ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
		UserDao userDao = (UserDao) context.getBean("aProxy");
		userDao.save();

		System.out.println("-------------");

		AInterface a = (AInterface)userDao;
		a.say();

		System.out.println("-------------");
		userDao.save();

f、结果

方法执行前执行
org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation
save
保存用户...
方法执行后执行
-------------
方法执行前执行
org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation
say
UserDao要说话
方法执行后执行
-------------
方法执行前执行
org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation
save
保存用户...
方法执行后执行
时间: 2024-09-20 20:19:41

第三章 AOP 通过Java API创建增强的相关文章

第三章 AOP 通过Java API创建切面

    在前面使用增强的时候,我们发现增强会被织入到目标类的所有的方法中.我们如果把增强织入到目标类的特定的方法中,需要使用切点进行目标连接点的定位.然后我们可以通过切点及增强生成一个切面了. 3.4.1切点类型 静态方法切点:org.springframework.aop.support.StaticMethodMatcherPointcut 动态方法切点:org.springframework.aop.support.DynamicMethodMatcherPointcut 注解切点:org

第三章 AOP 基于Schema的AOP

        基于Schema定义的切面和前现两种方式定义的切面,内容上都差不多,只是表现形式不一样而已. 3.7.1一般增强的使用 a.目标类 public class Target { public void say(){ System.out.println("say..."); } public String getName(int id,String name){ System.out.println("getName..."); return &quo

第三章 AOP 自动创建代理

3.5.1BeanNameAutoProxyCreator         在之前的切面使用中,最后得通过ProxyFactoryBean类生成一个代理类,然后通过代理类对象获取目标类与目标类织入的增强信息.一个代理类对应一个目标类.如果我们有多个目标类的切面信息(切点与增强)都一样的,而我们必须在spring的配置文件中配置多个代理类来为多个目标类设置代理.                  BeanNameAutoProxyCreator可以为多个Bean名字类似的目标类进行代理设置,而且多

第三章 AOP 编程选择

         Spring为我们开发者提供了多种AOP的编程方式.我们该如何选择呢? 如果项目采用的是JDK5.0以上版本,我们可以选择@AspectJ的方式.这是第一选择. http://blog.csdn.net/p_3er/article/details/9268637 如果使用的是低版本的JDK,那么可以考虑使用<aop:aspect>,也就是Schema的方式. http://blog.csdn.net/p_3er/article/details/9269407 如果需要一些特殊

Java初级笔记-第三章

第三章 程序设计基础 3.1 流程图 3.1.1 什么是流程图: 流程图是通过箭头(流程线)相互连接的几何图形来表达程序运行的方法. 流程图是算法的一种图形化描述,比较直观的表达了一件事务的处理过程.相对于代码来讲容易理解. 3.1.2 流程图的组成: 画流程图的方法是:从左到右.从上到下.根据问题的需要,确定解决问题的先后处理顺序以及前提条件,将流程线将各图形符号连接起来,直观的表达自己的逻辑思想或问题的处理方法,最终达到预期的结果. 注意事项: 一个流程图只能有一个开始框,开始框作为处理问题

Pro JavaScript Techniques第三章: 创建可重用的代码

 Pro JavaScript Techniques第三章: 创建可重用的代码 mozart0 [楼主] 匪徒田老大 版主 帖子 2326体力 6628 威望 177 注册 2003-6-18 #1 发表于 2007-4-8 12:46  资料  短消息  加为好友  Pro Javascript Techniques翻译连载:说明和目录 当与其它程序员共同开发代码时(这里对大多数合作或团队项目来说是很常见的),为了保持你们的清醒而维护良好的编程惯例将会变得极其重要.随着近年来JavaScrip

DB2 NoSQL JSON 功能(三) 使用 Java API 编写应用程序

管理 JSON 文档 - 使用事务和不使用事务 概述 简介 DB2 JSON 是一个可用于 DB2 Linux, Unix and Windows 10.5 的 Technology Preview,提供了以下特性: 一个命令行 shell 用于管理和查询 JSON 数据 一个 Java API 用于应用程序开发 一个有线监听器用于接受和响应通过网络发送的请求. 图 1. DB2 JSON 组件 本文将介绍如何使用 Java 接口管理和查询 DB2 JSON 文档存储中的 JSON 文档.还将讨

《Android游戏开发详解》——第2章,第2.18节使用Java API中的对象

2.18 使用Java API中的对象Android游戏开发详解现在,让我们暂时从创建自己的类告一段落,来享受一下Java自带的现成的类.使用已有的编程语言,而不是自己创造一种编程语言,其好处在于你可以获取已有的代码,并且在自己的项目中实现它们.好在对于我们来说,Java类配备了内容广泛的文档,涉及它们所包含的变量.如何初始化这些变量,以及它们执行哪些行为,从而我们可以将这些类用于自己的程序,并且只关注它们特定于我们的项目的重要问题.

Android群英传笔记——第三章:Android控件架构与自定义控件讲解

Android群英传笔记--第三章:Android控件架构与自定义控件讲解 真的很久没有更新博客了,三四天了吧,搬家干嘛的,心累,事件又很紧,抽时间把第三章大致的看完了,当然,我还是有一点View的基础的,可以先看下我之前写的几篇基础的View博客 Android绘图机制(一)--自定义View的基础属性和方法 Android绘图机制(二)--自定义View绘制形, 圆形, 三角形, 扇形, 椭圆, 曲线,文字和图片的坐标讲解 Android绘图机制(三)--自定义View的三种实现方式以及实战