`
bcyy
  • 浏览: 1826090 次
文章分类
社区版块
存档分类
最新评论

Aop 通知例子

 
阅读更多

连接点(Joinpoint)(要被拦截的方法):并不是所有被spring管理的对象的所有方法都是连接点,在Spring AOP中,一个连接点总是表示一个方法的执行。

切入点:使用表达式,哪些切入点需要被切入。

切面:一个关注点的模块化,这个关注点可能会横切多个对象。就是要拦截的类。

织入(Weaving):把切面连接到其它的应用程序类型或者对象上,并创建一个被通知的对象。切点把切面织入进来。

通知(Advice):在切面的某个特定的连接点上执行的动作。其中包括了“around”、“before”和“after”等不同类型的通知

目标对象(Target Object): 被一个或者多个切面所通知的对象。也被称做被通知(advised)对象。被代理对象,实际对象

(切面上的通知)

当连接点被调用时,告知切入点要切入哪个方法,引入切面,切面拦截,然后去通知。

例子:导入aopalliance.jar、aspectjweaver.jar

beans.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" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
	default-lazy-init="false" default-autowire="no">
	
	<bean id="Myservice" class="org.hzy.services.MyService"/>
	<bean id="MyAdvice" class="org.hzy.advices.MyAdvice"/>
	
    <aop:config><!-- 只需要一个就可以包含多个切面 -->  
        <aop:pointcut id="before" expression="execution(* org.hzy.services.MyService.add_user(..))"/><!-- 顶级切点 --> 
        <aop:pointcut id="around" expression="execution(* org.hzy.services.MyService.add(Integer,String))"/>
        <aop:aspect ref="MyAdvice"><!-- 一个切面包含多个通知 -->  
            <aop:before method="doBefore" pointcut-ref="before"/>  
            <!-- <aop:after method="doAfter" pointcut-ref="before"/>-->  
              
            <!-- returning 注册变量来接收方法的返回值 -->  
            <aop:after-returning method="doAfter" pointcut="execution(* org.hzy.services.MyService.add())" returning="ss" />   
			
			<!-- throwing 注册变量来接收方法产生的异常-->
			<aop:after-throwing throwing="ex" pointcut="execution(* org.hzy.services.MyService.add(Integer))" method="doThrow"/>
			
			<aop:around method="doAround" pointcut-ref="around"/>
		</aop:aspect>
	</aop:config>
</beans>
传参数还可以用args,在表达式里面 在通知中args-name

自定义异常类Myexception.java

package org.hzy.exceptions;

public class MyException extends Exception{//自定义异常
	public MyException(String msg){
		super(msg);
	}
}

IMyService.java

package org.hzy.services;

import org.hzy.exceptions.MyException;

public interface IMyService { //实现接口的方法才是连接点
	public void add_user(String uname);
	
	public String add();
	
	public void add(Integer i) throws MyException;
	
	public void add(Integer i,String uname);
}


MyService.java

package org.hzy.services;

import org.hzy.exceptions.MyException;

public class MyService implements IMyService{
	public void add_user(String uname){
		System.out.println("add_user!!!!!!"+uname);
	}
	public String add(){
		System.out.println("add!!!!!!!!!!!");
		return "hzy";
	}
	public void add(Integer i) throws MyException{//声明异常
		System.out.println("add with args i!!!!!!!!!!!");
		String a=null;
//		try { //在这里捕获异常后将不会走拦截方法
//			System.out.println(a.equals(i));
//		} catch (Exception e) {
//			// TODO: handle exception
//		}
		throw new MyException("wrong!!!!!!!!!!");
//		System.out.println(a.equals(i));
	}
	
	public void add(Integer i,String uname){
		System.out.println("this is add with args uname"+i+" "+uname);
	}
}

MyAdvice.java(切面类)

package org.hzy.advices;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

public class MyAdvice {
	//前置通知不能改变参数,是只读的
	public void doBefore(JoinPoint jp){
		System.out.println(jp.getTarget());//得到目标对象,也是被代理对象,真正的对象
		System.out.println(jp.getArgs()[0]);
		System.out.println(jp.getSignature().getName());//得到方法名
		System.out.println("this is doBefore");
	}
	//后置拦截,一般使用After-returning
	public void doAfter(JoinPoint jp,Object ss){//至少两个参数,这个参数名必须是ss且是第0位
		System.out.println(ss);
		System.out.println("this is doAfter");
	}
	
	public void doThrow(JoinPoint jp,Exception ex){//在异常发生前调用
		System.out.println(ex+"   "+ex.getMessage());
		System.out.println("this is doThrow");
	}
	//环绕通知,要手动调用,连接点被包住,使用连接点的子类ProceedingJoinPoint
	public void doAround(ProceedingJoinPoint pjp) throws Throwable{//Throwable异常比exception异常高
		System.out.println("this is doAround");
		if(Integer.parseInt(pjp.getArgs()[0].toString())<10){//传过来的值是12,aa
			System.out.println("小于10");
		}else{
			Object o=pjp.proceed(new Object[]{new Integer(20),"hzy"});//调用下一个,在调用连接点方法之前,可以改变值,不像前置通知,如果不改变的话,可以直接pjp.proceed();
			System.out.println(o);//是null,void的返回值是null
		}
	}
}
自定义异常将会把异常消息被异常通知拦截

MyTest.java

package org.hzy.test;

import org.hzy.exceptions.MyException;
import org.hzy.services.IMyService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest1 {
	public static void main(String[] args) throws MyException {
		ApplicationContext ctx=new ClassPathXmlApplicationContext("beans1.xml");
//		MyService my=ctx.getBean("Myservice",MyService.class);//Add CGLIB to the class path or specify proxy interfaces
		IMyService my=ctx.getBean("Myservice",IMyService.class);//由于返回的是代理,代理与MyService不相干,不能转换,所有要实现接口
//		my.add_user("hzy");
//		my.add();
		
//		my.add(1);
/*		try {
			my.add(1);
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println("错误!!!!!!!!!!!");//会先走拦截方法
		}*/
		
		my.add(12,"aa");
			
	}
}


注:new 出来的是不会别切入拦截的,要spring中的

当没有实现接口的时候,报错,增加CGLIB包或者增加代理接口

Spring发现被切入的对象实例,返回的是代理,所以通过getBean得到的是代理($proxy)

向Spring容器要MyService对象,却返回个代理,这个代理和MyService对象不相关,不能转换,所以实现接口,代理也实现接口。所以,

接口中的方法才是真正的接入点。

动态代理:(因为编译好的类是不能修改的,所以需要代理)

MyServiceProxy也实现了接口,里面有MyService这个属性,当被切入拦截的时候,在代理的add_user()中,

MyService mys;是Spring产生的

public void add_user(String name){

加了拦截的代码

mys.add_user(name);

}


分享到:
评论

相关推荐

    springAOP演示例子

    springAOP小例子 装配器 切入点 通知等

    Spring 使用AspectJ 实现 AOP之前置通知小例子

    Spring 使用AspectJ 实现 AOP之前置通知小例子,实际跑过,验证可信。

    myeclipse spring IOC和AOP 例子

    关于Spring的IOC和AOP的例子,帮助初学者入门。 内有bean的声明、注入;切入点和通知等功能例子。 环境配置:myeclipse, spring2.5

    Sping aop简单示例

    包含aop的5中通知的示例,用的原始的xml配置方法

    aop的详细总结(包含例子)

    一、AOP 概念 二、AOP 种类 三、Spring AOP 代理原理 四、Spring AOP 通知类型 五、Spring AOP Pointcut 六、Spring AOP 中的Advisor其实就是Aspect 七、AOP ProxyFactory 八、自动代理

    Spring-AOP(前置/后置/环绕)通知的例子

    NULL 博文链接:https://z18022893621.iteye.com/blog/1956146

    spring通知例子

    本例是一个很好的springAop使用例子,例子举例了spring的前置通知和后置通知的使用方法。用以拦截操作日志。

    Spring实现AOP的多种方式 切点函数

    里面包括4个例子:(1)Spring实现AOP方式之一:基于XML配置的Spring AOP (2)Spring实现AOP方式之二:使用注解配置 Spring AOP (3)Spring AOP : AspectJ Pointcut 切点 (4)Spring AOP : Advice 声明 (通知注解)

    spring aop 示例

    spring aop的编程例子,里面包括基本的PointCut定义,通知定义,引入。可以直接运行,方便对照书籍学习。

    SpringFramework中的面向方面编程(AOP),第二部分

    跟踪和记录方面提供了非常不错的上手例子,而本文将进一步介绍一种新的通知形式:around通知。比起第一部分中介绍的那些通知类型,around形式的通知是一种更具侵入性也更强大的面向对象概念。本文将描述around通知的...

    SpringFramework中的AOP编程之入门篇

    使用跟踪和记录方面(面向方面领域的HelloWorld)作为例子,本文展示了如何使用Spring框架所独有的特性来声明切入点和通知以便应用方面。本系列的第二部分将更深入地介绍如何运用Spring中的所有通知类型和切入点来...

    SpringFramework中的面向方面编程(AOP),第一部分

    使用跟踪和记录方面(面向方面领域的HelloWorld)作为例子,本文展示了如何使用Spring框架所独有的特性来声明切入点和通知以便应用方面。本系列的第二部分将更深入地介绍如何运用Spring中的所有通知类型和切入点来...

    spring.net中文手册在线版

    20.5.1.向CAO对象应用AOP通知 20.6.在客户端访问CAO 20.6.1.向客户端的CAO对象应用AOP通知 20.7. XML Schema for configuration 20.8.参考资源 第二十一章. .NET企业服务 21.1.简介 21.2.服务组件 21.3.服务端 21.4....

    Spring-Reference_zh_CN(Spring中文参考手册)

    2.3. 面向切面编程(AOP) 2.3.1. 更加简单的AOP XML配置 2.3.2. 对@AspectJ 切面的支持 2.4. 中间层 2.4.1. 在XML里更为简单的声明性事务配置 2.4.2. JPA 2.4.3. 异步的JMS 2.4.4. JDBC 2.5. Web层 2.5.1. Spring MVC...

    spring.doc

    异常通知处理例子: 91 不用spring异常通知,另一种处理异常 96 4.2.2.2Aop注解形式(了解) 99 注解注入拓展: 103 5 Spring数据库 106 5.1 Spring+JDBC 106 5.1.1 Jdbc编程特点 106 5.1.2引入DataSource 106 5.1.3...

    Spring 2.0 开发参考手册

    2.3.1. 更加简单的AOP XML配置 2.3.2. 对@AspectJ 切面的支持 2.4. 中间层 2.4.1. 在XML里更为简单的声明性事务配置 2.4.2. JPA 2.4.3. 异步的JMS 2.4.4. JDBC 2.5. Web层 2.5.1. Spring MVC的表单标签库 ...

    spring chm文档

    2.3.1. 更加简单的AOP XML配置 2.3.2. 对@AspectJ 切面的支持 2.4. 中间层 2.4.1. 在XML里更为简单的声明性事务配置 2.4.2. JPA 2.4.3. 异步的JMS 2.4.4. JDBC 2.5. Web层 2.5.1. Spring MVC的表单标签库 ...

Global site tag (gtag.js) - Google Analytics