spring(二)面向切面的AOP代理

版权声明:版权所有,如需转载,请注明出处 https://blog.csdn.net/houdezaiwu1/article/details/83690312

面向切面编程,就是在不改变源代码的基础上,增加新的功能,对代码进行增强处理,代理模式。

关注两件事:在什么位置,执行什么功能。由Spring AOP完成织入工作,日志、异常处理、事务控制等。

增强处理主要有:

  • 前置增强  before  在切入点前边执行
  • 后置增强  after-returning   在切入点后边执行,如果有异常,就不执行
  • 最终增强 after      在切入点后边执行,无论怎样都会执行,
  • 环绕增强 round    最强大的增强,封装了目标对象,对其进行控制。
  • 异常抛出增强  after-throwing  发生异常执行

首先添加需要的架包: aopalliance-1.0.jar;aspectjweaver-1.6.9.jar;spring-aop-3.2.13.RELEASE.jar

一、配置aop

1. 定义包含增强方法的javaBean

package aop;

import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

public class AopLogger {
	private static final Logger log = Logger.getLogger(AopLogger.class);
	public void before(JoinPoint jp){
		log.info("=====>前置增强: 调用 "+jp.getTarget()+"的"+jp.getSignature().getName()+" 方法,方法入参:"+jp.getArgs().toString());
	}
	public void after(JoinPoint jp){
		log.info("=====>最终增强:调用 "+jp.getTarget()+"的"+jp.getSignature().getName()+" 方法");
	}
	public void afterReturning(JoinPoint jp,Object result){
		log.info("=====>后置增强带返回值:调用 "+jp.getTarget()+"的"+jp.getSignature().getName()+" 方法,返回值:"+result);

	}
	public void afterException(JoinPoint jp,Exception e){
		log.info("=====>异常抛出增强 "+ jp.getSignature().getName() + "抛出异常"+e);
	}
	public void around(ProceedingJoinPoint jp) throws Throwable{
		//环绕增强得到了目标方法的控制权,可以获取、修改目标方法的参数和返回值,封装了目标对象,达到点对点的控制
		log.info("=====>环绕增强执行 ");            //相当于前置增强  
		try{
			Object result = jp.proceed();      
			log.info("\n=====> 环绕增强结果 :"+result); //相当于后置增强
		}catch(Throwable e){
			log.info("=====>环绕增强抛出异常:"+e);    //相当于异常抛出增强
			throw e;
		}finally{
			log.info("=====>环绕增强最后 ");   //相当于最终增强
		}
		
	}
}

spring 会自动注入JoinPoint 实例。

2..创建目标对象

package aop;

public class PointDemo {
	public String method1(String name){
		System.out.println("======> 执行 method1, name is : "+name);
		return name;
	}
}

method1作为切入点

3. 配置applicationContext.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:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/aop
		http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
<!--注入实例  -->	
<bean id="pointDemo" class="aop.PointDemo"></bean>	
<bean id="aopLogger" class="aop.AopLogger"></bean>
<aop:config>
	<!--1. 定义一个切入点  -->
	<aop:pointcut expression="execution(public * method1(..))" id="pointCut"/>
	<!-- 2. 引用包含增强方法的Bean -->
	<aop:aspect ref="aopLogger">
		<aop:before method="before" pointcut-ref="pointCut"/><!--前置增强  -->
		<aop:after method="after" pointcut-ref="pointCut"/><!-- 最终曾强  不论是否发生异常都执行-->
		<aop:after-returning method="afterReturning" pointcut-ref="pointCut" returning="result"/><!-- 带返回值的后置增强  有异常就不执行了 -->	
		<aop:after-throwing method="afterException" pointcut-ref="pointCut" throwing="e"/> <!-- 异常抛出增强 -->
		<aop:around method="around" pointcut-ref="pointCut"/>
	</aop:aspect>
</aop:config>
</beans>		
	

有关aop的配置都放在<aop: config> 标签内;配置切入点的标签<aop: pointcut>的expression属性有多种表达式:

  • public * method1(String name);    匹配所有返回值类型
  • public  void * (name);  匹配所有方法名
  • public void method1(..);  “..”匹配所有类型返回值;
  • * com.*.*(..);      匹配com包下所有的类的方法;
  • * com..*.*(..);    匹配com包及其子包所有类的方法

4. 测试

package aop;

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

public class Test {
	public static void main(String[] args) {
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext1.xml");
		PointDemo pd = (PointDemo)ac.getBean("pointDemo");
		pd.method1("张三");
	}
}

讲环绕增强注释掉的结果:

INFO - =====>前置增强: 调用 aop.PointDemo@72057ecf的method1 方法,方法入参:[Ljava.lang.Object;@6e171cd7
======> 执行 method1, name is : 张三
INFO - =====>最终增强:调用 aop.PointDemo@72057ecf的method1 方法
INFO - =====>后置增强带返回值:调用 aop.PointDemo@72057ecf的method1 方法,返回值:张三

加上环绕增强的结果:

INFO - =====>前置增强: 调用 aop.PointDemo@dbf57b3的method1 方法,方法入参:[Ljava.lang.Object;@52e6fdee
INFO - =====>环绕增强执行 
INFO - 
=====> 环绕增强结果 :张三
======> 执行 method1, name is : 张三
INFO - =====>环绕增强最后 
INFO - =====>后置增强带返回值:调用 aop.PointDemo@dbf57b3的method1 方法,返回值:null
INFO - =====>最终增强:调用 aop.PointDemo@dbf57b3的method1 方法 

可以看到,后置增强返回值为null,所以环绕增强最好别和其他的一起用。

5. 改造 目标类,使其发生异常,测试异常抛出增强;

package aop;

public class PointDemo {
	public String method1(String name){
		System.out.println("======> 执行 method1, name is : "+name);
		String str="";
		System.out.println(str.equals(""));
		return name;
	}
}

 测试异常:

INFO - =====>前置增强: 调用 aop.PointDemo@dbf57b3的method1 方法,方法入参:[Ljava.lang.Object;@52e6fdee
INFO - =====>环绕增强执行 
======> 执行 method1, name is : 张三INFO - =====>环绕增强抛出异常:java.lang.NullPointerException
INFO - =====>环绕增强最后 

INFO - =====>异常抛出增强 method1抛出异常java.lang.NullPointerException
INFO - =====>最终增强:调用 aop.PointDemo@dbf57b3的method1 方法
Exception in thread "main" java.lang.NullPointerException
    at aop.PointDemo.method1(PointDemo.java:7)
    at aop.PointDemo$$FastClassBySpringCGLIB$$93985287.invoke(<generated>)

抛出了异常。 

猜你喜欢

转载自blog.csdn.net/houdezaiwu1/article/details/83690312
今日推荐