`
Luob.
  • 浏览: 1572924 次
  • 来自: 上海
社区版块
存档分类
最新评论

spring 第10 天 AOP 面向切面

阅读更多
AOP(Aspect Orient Programming)也就是 面向切面编程,AOP和OOP 互补

<?xml version="1.0" encoding="UTF-8"?>
<!--  采用 DTD 来约束spring 配置文件
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
-->
<!-- 下面采用 XML Schema 约束-->
<!--default-autowire-candidates="*abc" 该bens 下面的 所以以abc 结尾的 bean 不作为 自动注入的bean  -->
<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"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans   
    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd   
    http://www.springframework.org/schema/tx   
    http://www.springframework.org/schema/tx/spring-tx-3.2.xsd 
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.2.xsd 
    http://www.springframework.org/schema/context  
    http://www.springframework.org/schema/context/spring-context-3.2.xsd  
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
    
<!--自动搜索bean组件,自动搜索切面类--->
    <context:component-scan base-package="annotation.model,annotation.aop">
    	<context:include-filter type="annotation" expression="org.aspectj.lang.annotation.Aspect"/>
    </context:component-scan>
    
    <!-- 这种表示全部使用 注解来配置aop  而且采用cglib来生成代理-->
    <aop:aspectj-autoproxy proxy-target-class="true"/>
    
   	<!--如果不采用 XML Schema配置方式,则需要配置 下面的bean
   	<bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"/>
    -->
</beans>

package annotation.aop.point;

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

//定义一个切面
@Aspect
public class SystemArchitecture {

	/**
	 * execution(pat1 pat2  pat3  pat4 pat5 pat6)  包含6部分
	 * pat1 : modifiers-pattern: 方法的修饰符  public default protected private  可以省略 
	 * pat2 : ret-type-pattern: 方法的返回值类型    "*" 表示匹配所有的返回值类型
	 * pat3 : decaring-type-pattern: 指定方法所属的类   支持通配符  ,可以省略.
	 * pat4 : name-pattern: 方法名字 ,支持通配符, 可以使用 * 匹配所有方法
	 * pat5 : param-pattern: 方法 的参数列表 "*" 表示一个任意类型的参数  ".." 任意个数任意类型的参数 
	 * pat6 :throws-pattern: 指定方法声明抛出的异常,支持通配符,可以省略
	 * 
	 */
	
	//定义一个 切入点
	// 这个表达式 是   pat1=(省略) pat2=*  pat3=annotation.model.impl.Peo* pat4=eat* pat5=(..) pat6=(省略) 
	@Pointcut("execution(* annotation.model.impl.Peo*.eat*(..))")
	public void myPointcut(){
		
	}
	
	//匹配所有 public 方法 
	@Pointcut("execution(public * * (..))")
	public void pintcut1(){
		
	}
	
	//所有set 开头的方法
	@Pointcut("execution(* set*(..))")
	public void pintcut2(){
		
	}
	
	//所有impl 包下所有类的所有方法
	@Pointcut("execution(* annotation.model.impl.*.*(..))")
	public void pintcut3(){
		
	}
	
	//所有People类 下的所有 方
	@Pointcut("execution(* annotation.model.impl.People.*(..))")
	public void pintcut4(){
		
	}
	
	//impl 包中的所有 连接点
	@Pointcut("within(annotation.model.impl.*)")
	public void pintcut5(){
		
	}
	//impl 和 impl 子包中的所有 连接点
	@Pointcut("within(annotation.model.impl..*)")
	public void pintcut6(){
		
	}
	
	//匹配实现了Perosn接口的目标对象的所有连接点
	@Pointcut("this(annotation.model.interfaces.Person)")
	public void pintcut7(){
		
	}
	
	//限定目标对象 必须是指定类的实例
	@Pointcut("target(annotation.model.interfaces.Person)")
	public void pintcut8(){
		
	}
	
	//对连接点的参数类型进行设置
	//匹配只接受一个参数.且是 Serializable的所有连	接点
	//和 execution的区别是 args 是匹配运行时候的 参数类型
	//execution 是匹配方法签名 时候的参数类型
	@Pointcut("args(java.io.serializabel)")
	public void pintcut9(){
		
	}
	
	//匹配以People的bean 内的连接点
	@Pointcut("bean(*People)")
	public void pintcut10(){
		
	}
		
	
	//匹配以stoneAxe 内方法的连接点
	@Pointcut("bean(stoneAxe)")
	public void pintcut11(){
		
	}
	
	
	@AfterReturning(pointcut="myPointcut() && args(name,..)",returning="rtv")
	public void writeLog(String name,Object rtv){
		System.out.println("内部");
		System.out.println("参数值name:"+name);
		System.out.println("返回值:"+rtv);
	}
	
	
}


//before 在方法之前执行
package annotation.aop;

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

@Aspect
public class BeforeAdviceTest{
	
	@Before("execution(* annotation.model.impl.*.*(..))")
	public void authrity(){
		System.out.println("before: 模拟执行权限检查");
	}
	
}



//afterReturning 只有在目标方法执行完后被织入,能够获取方法的返回值,如果中途出现异常了,就不会被增强
package annotation.aop;

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class AfterRetruningAdviceTest {
	
	//只有 在方法 完成返回后 才能执行 如果中间 出现异常了 是不会执行的
	@AfterReturning(returning="rvt",pointcut="execution(* annotation.model.impl.*.*(..))")
	public void log(Object rvt){   //如果是Object 则 返回值 为任意类型的 都会被拦截 进行处理
		System.out.println("AfterReturning获取目标返回值:"+rvt);
		System.out.println("AfterReturning 模拟记录日志功能...");
	}
	
	@AfterReturning(returning="rvt",pointcut="execution(* annotation.model.impl.*.*(..))")
	public void log(int rvt){ //只拦截  返回值为 int的 方法  
		System.out.println("AfterReturning 我要的结果:"+rvt);
	}
}



//AfterThrowing 主要用于处理程序中未处理的异常,能够指定值增强抛出那些异常的方法
package annotation.aop;

import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
//@Component
public class AfterThrowingAdviceTest {

	//可以  指定只抛出指定的异常  可以对抛出的异常进行处理,但是不能对异常进行完全处理,异常还是会向上抛出 
	@AfterThrowing(throwing="ex",pointcut="execution(* annotation.model.impl.*.*(..))")
	public void doRecoveryActions(Throwable ex){  //NullPointerException ex
		System.out.println("AfterThrowing 目标方法中抛出的异常:"+ex);
		System.out.println("AfterThrowing 模拟抛出异常后的增强处理...");
	}
	
}


//after  不管目标方法 怎么结束(正常结束,抛出异常结束) 都会织入, 所以类是 finally{}
package annotation.aop;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class AfterAdviceTet {

	//类是 finally{
			//dosomething...
    //}
	@After("execution(* annotation.model.impl.*.*(..))")
	public void release(){
		System.out.println("After 模拟方法结束后关闭资源");
	}
}


//Around (before + afterReturning) 该增强处理比较强大,
比before强大; 在目标方法执行前,进行增强,可以决定 目标方法 是否执行,和什么时候执行.可以改变目标方法的参数值(也可以阻止目标方法执行)

比afterReturning强大: 可以在方法正常结束后进行增强, 可以改变方法的返回值.

注意:由于 Around 功能强大,因此需要在线程安全的环境下使用,如过用 before 和afterReturning能够解决的问题,就没必要 用 Around 了
package annotation.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class AroundAdviceTest {

	@Around("execution(* annotation.model.impl.*.*(..))")
	public Object proccesTx(ProceedingJoinPoint jp) throws Throwable{
		System.out.println("Around :执行目标方法前开始事务");
		Object rvt=jp.proceed(new String[]{"被改变的参数"});
		System.out.println("Around:执行目标方法之后,模拟结束事务");
		return rvt+"Around:新增的内容";
	}
}



//访问目标方法的 参数
//Object[] getArgs(): 获取目标方法的参数
//Sigature getSignature()返回被增强法方法的相关信息
//Object getTarget() 返回被织入 增强处理的目标对象
//Object getThis()  返回AOP框架为目标对象生成的代理对象
//==============================================
package annotation.aop;


import java.util.Arrays;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Aspect
@Order(1)
//@Component
public class FourAdviceTest {
	static{
		System.out.println("aop 1");
	}
	
	
	@Around("execution(* annotation.model.impl.*.*(..))")
	public Object processTx(ProceedingJoinPoint jp) throws Throwable{
		System.out.println("-------------------Around增强: 执行目标方法前 ,模拟开始事务....");
		
		//获取执行目标方法的参数
		Object[] args=jp.getArgs();
		if(args!=null && args.length>0 && args[0].getClass() == String.class){
			args[0]="被改变的参数";
		}
		Object rvt=jp.proceed(args);
		System.out.println("Around增强:执行目标方法之后,模拟结束事务...");
		return rvt+"新增的内容";
	}
	@Before("execution(* annotation.model.impl.*.*(..))")
	public void authority(JoinPoint jp){
		System.out.println("-------------------Before增强处理:");
		System.out.println("模拟执行权限检查");
		System.out.println("被织入增强处理的目标方法为"+jp.getSignature().getName());
		System.out.println("目标方法参数为:"+Arrays.toString(jp.getArgs()));
		System.out.println("被织入增强处理的目标对象为:"+jp.getTarget());
	}
	
	@AfterReturning(pointcut="execution(* annotation.model.impl.*.*(..))",returning="rvt")
	public void log(JoinPoint jp,Object rvt){
		System.out.println("-------------------AfterReturning增强处理");
		System.out.println("获取目标返回值:"+rvt);	
		System.out.println("模拟日志记录功能");
		System.out.println("被织入增强处理的目标方法为"+jp.getSignature().getName());
		System.out.println("目标方法参数为:"+Arrays.toString(jp.getArgs()));
		System.out.println("被织入增强处理的目标对象为:"+jp.getTarget());
	}
	
	@After("execution(* annotation.model.impl.*.*(..))")
	public void release(JoinPoint jp){
		System.out.println("-------------------After增强处理");
		System.out.println("模拟方法结束后,释放资源");
		System.out.println("被织入增强处理的目标方法为"+jp.getSignature().getName());
		System.out.println("目标方法参数为:"+Arrays.toString(jp.getArgs()));
		System.out.println("被织入增强处理的目标对象为:"+jp.getTarget());
	}
	
}



采用XML配置文件来配置AOP
<?xml version="1.0" encoding="UTF-8"?>
<!--  采用 DTD 来约束spring 配置文件
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
-->
<!-- 下面采用 XML Schema 约束-->
<!--default-autowire-candidates="*abc" 该bens 下面的 所以以abc 结尾的 bean 不作为 自动注入的bean  -->
<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"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans   
    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd   
    http://www.springframework.org/schema/tx   
    http://www.springframework.org/schema/tx/spring-tx-3.2.xsd 
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.2.xsd 
    http://www.springframework.org/schema/context  
    http://www.springframework.org/schema/context/spring-context-3.2.xsd  
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">


    <context:component-scan base-package="annotation.model,annotation.aop">
    </context:component-scan> 
    
    <!--使用xml来配置AOP -->
   	<!-- 定义一个切面类 
   	<bean id="fourAdvice" class="annotation.aop.FourAdviceTest"/>
   	<bean id="fourAdvice1" class="annotation.aop.FourAdviceTest1"/>
   	 -->
   	 <!-- proxy-target-class="false": 默认 采用 com.sun.proxy 代理(表示被代理的类必须是实现了接口,纯 接口实现类)
   	 如果被代理的累是 一个javaBean 则 只能使用 cglib 创建代理 
   	 expose-proxy="true" : 决定当前代理是否被暴露在一个ThreadLocal 中以便被目标对象访问。
   	 	如果目标对象需要获取代理而且exposeProxy属性被设为 true,
   	 	目标对象可以使用AopContext.currentProxy()方法。
   	  -->
   <aop:config proxy-target-class="true">
   		<aop:pointcut id="pt1" expression="execution(* annotation.model.impl.*.*(..))"/>
   		
   		<aop:aspect id="oneAdvice" ref="fourAdvice" order="1">
   			<aop:after method="release" pointcut-ref="pt1"/>
   			<aop:before method="authority" pointcut-ref="pt1"/>
   			<aop:after-returning returning="rvt" method="log" pointcut-ref="pt1"/>
   			<!-- 匹配返回值为 String的 -->
   			<aop:around method="processTx" pointcut="execution(String annotation.model.impl.*.*(..))"/>
   		</aop:aspect>
   		
   		<!-- 注解的时候 使用 &&  || !
   			在使用XML配置的时候 使用  and  or  not
   		 -->
   		<aop:aspect id="twoAdvice" ref="fourAdvice1" order="2">
   			<aop:pointcut  id="pt2" expression="execution(* annotation.model.impl.*.*(..)) and args(name)"/>
   			<aop:before method="authority" pointcut-ref="pt2"/>
   		</aop:aspect>
   		
   		<aop:aspect id="errorAdvice" ref="afterThrowingAdviceTest" order="1">
   			<aop:after-throwing method="doRecoveryActions" pointcut-ref="pt1" throwing="ex"/>
   		</aop:aspect>
   	</aop:config>
 
</beans>
分享到:
评论

相关推荐

    第十四章面向切面编程(SpringAOP)PPT文档.pptx

    第十四章面向切面编程(SpringAOP)PPT文档.pptx

    Spring的学习笔记

    第七课:AOP(面向切面编程) 19 一、 AOP概念 19 二、 利用动态代理实现面向切面编程 20 第八课:Spring AOP配置选项 21 一、 AOP配置annotation方式 21 (一) 搭建annotation开发环境 21 (二) aspectJ类库 22 (三) ...

    Spring in Action 中文版 第2版 第二部分

    书中第一部分展示了Spring框架的两个核心特性:依赖注入和面向切面编程。第二部分以第一部分介绍的DI和AOP特性为基础,叙述了如何将这两个概念应用到应用程序的数据和业务层中。第三部分介绍了Spring构建 Web应用...

    Spring in Action 中文版 第2版 第一部分

    书中第一部分展示了Spring框架的两个核心特性:依赖注入和面向切面编程。第二部分以第一部分介绍的DI和AOP特性为基础,叙述了如何将这两个概念应用到应用程序的数据和业务层中。第三部分介绍了Spring构建 Web应用...

    spring2.5 学习笔记

    第七课:AOP(面向切面编程) 19 一、 AOP概念 19 二、 利用动态代理实现面向切面编程 20 第八课:Spring AOP配置选项 21 一、 AOP配置annotation方式 21 (一) 搭建annotation开发环境 21 (二) aspectJ类库 22 (三) ...

    Spring 2.0 开发参考手册

    6. 使用Spring进行面向切面编程(AOP) 6.1. 简介 6.1.1. AOP概念 6.1.2. Spring AOP的功能和目标 6.1.3. Spring的AOP代理 6.2. @AspectJ支持 6.2.1. 启用@AspectJ支持 6.2.2. 声明一个切面 6.2.3. 声明一个...

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

    6. 使用Spring进行面向切面编程(AOP) 6.1. 简介 6.1.1. AOP概念 6.1.2. Spring AOP的功能和目标 6.1.3. Spring的AOP代理 6.2. @AspectJ支持 6.2.1. 启用@AspectJ支持 6.2.2. 声明一个切面 6.2.3. 声明一个切入点...

    spring chm文档

    6. 使用Spring进行面向切面编程(AOP) 6.1. 简介 6.1.1. AOP概念 6.1.2. Spring AOP的功能和目标 6.1.3. Spring的AOP代理 6.2. @AspectJ支持 6.2.1. 启用@AspectJ支持 6.2.2. 声明一个切面 6.2.3. 声明一个...

    Spring中文帮助文档

    6. 使用Spring进行面向切面编程(AOP) 6.1. 简介 6.1.1. AOP概念 6.1.2. Spring AOP的功能和目标 6.1.3. AOP代理 6.2. @AspectJ支持 6.2.1. 启用@AspectJ支持 6.2.2. 声明一个切面 6.2.3. 声明一个切入点...

    Spring API

    6. 使用Spring进行面向切面编程(AOP) 6.1. 简介 6.1.1. AOP概念 6.1.2. Spring AOP的功能和目标 6.1.3. AOP代理 6.2. @AspectJ支持 6.2.1. 启用@AspectJ支持 6.2.2. 声明一个切面 6.2.3. 声明一个切入点...

    Spring面试题

    面向切面编程(AOP)完善spring的依赖注入(DI),面向切面编程在spring中主要表现为两个方面 1.面向切面编程提供声明式事务管理 2.spring支持用户自定义的切面 面向切面编程(aop)是对面向对象编程(oop)的...

    Java语言基础下载

    目录 第一章:Java开始 1 学习目标 1 Java历史 2 Java技术概述 3 Java技术的优点 3 ...AOP面向切面编程 715 AOP的专业术语 715 Spring事务管理 718 Spring与Struts整合 719 Spring与Hibernate整合 721 独立实践 724

    低清版 大型门户网站是这样炼成的.pdf

    6.1.4 何为“面向切面编程aop” 356 6.1.5 spring 2.5圣经——面向接口编程 358 6.1.6 开始spring 2.5旅程—hello world 359 6.2 spring 2.5核心技术 364 6.2.1 bean工厂之beanfactory介绍 364 6.2.2 实用的...

    JAVA程序开发大全---上半部分

    第10章 Spring框架的开发及应用 161 10.1 Spring框架概述 161 10.2 Spring框架中的IoC编程 162 10.2.1 控制反转的原理 163 10.2.2 控制反转中的主要组件 163 10.2.3 控制反转中的依赖注入方式 164 10.3 Spring框架中...

    Java/JavaEE 学习笔记

    第三章 Spring AOP(面向切面编程)..........351 第四章 Spring中的数据访问..........353 CVS学习笔记.................355 PL/SQL学习笔记............358 第一章 PL/SQL概述........................358 第二章 ...

    J2EE学习笔记(J2ee初学者必备手册)

    第三章 Spring AOP(面向切面编程)..........351 第四章 Spring中的数据访问..........353 CVS学习笔记.................355 PL/SQL学习笔记............358 第一章 PL/SQL概述........................358 第二章 PL...

    java面试题

    Spring AOP面向方面编程 82 74. 项目中为什么使用SSH 85 75. Spring在SSH中的作用 86 76. weblogic 86 76.1. 如何给weblogic指定大小的内存? 86 76.2. 如何设定的weblogic的热启动模式(开发模式)与产品发布模式? 86...

Global site tag (gtag.js) - Google Analytics