Spring-AOP面向切面编程

AOP是面向切面编程,区别于oop,面向对象,一个是横向的,一个是纵向。

主要解决代码分散和混乱的问题。

1.概念:

切面:实现AOP共有的类

通知:切面类中实现切面功能的方法

连接点:程序被通知的特定位置

切点:连接点的定义

代理:向目标应用通知而产生的对象

2.配置

 

AOP的实现的基本要求:通过接口创建目标的代理。

1。首先是配置文件,2。然后启动扫描器<context:component-scan>和启动AOP注解支持<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

3.之后再逻辑方法类上定义容器管理@Component(“名称”)若不写名称,则默认是类名首字母小写的名字。

3.定义切面类

定义容器管理@Component和@Aspect//切面类 

4.定义通知

通知可分为@before前置通知、@After后置通知、@AfterReturning返回通知、@AfterThrowing异常通知、@Around环绕通知。

前置通知:

在方法执行前执行,参数JoinPoint,代表连接点

可以得到参数列表和方法名

通过getNmae和        getAtgs,反回的是object[]类型

后置通知;在方法之后执行,同样可以获得参数列表和方法名

异常通知:

throwing=“接受异常对象规定参数”

 

 环绕通知:

 

 

5.定义切点表达式

@通知类型注解(pointCut=“execution(修饰符的返回值类型 包名.类名.方法名(参数类型))”)

6.公共切点@Pioneertcut

之后再调用切点表达式的时候直接写:通知类型(“公共切点表达式的类名piontCut”)

 

接口=============================

package com.hanqi.test;

import org.springframework.stereotype.Component;


public interface I_jsq {
	
	double add(double a ,double b);
	double div(double a ,double b);

}

  实现类业务逻辑类=========

package com.hanqi.test;

import org.springframework.stereotype.Component;

@Component("my1")//容器管理
public class Myjsq implements I_jsq {

	//连接点
	@Override
	public double add(double a, double b) {
		//前置通知的连接点
		
		//日志记录
//		System.out.println("日志:a = "+a+" ,b = "+b);
		System.out.println(a+"+"+b+"="+(a+b));

		if(a < 0)
		{
			throw new RuntimeException("运行时异常");
		}
		return(a+b);
		//后置通知的连接点
	}
	//连接点
	@Override
	public double div(double a, double b) {
		//日志记录
		//System.out.println("日志:a = "+a+" ,b = "+b);
		
		//检查
//		if(b==0)
//		{
//			System.out.println("b不能是0");
//			return -1;
//		}
//		else
//		{
			System.out.println(a+"/"+b+"="+(a/b));
			return (a/b);

		//}
	}

}

  切面类================

package com.hanqi.test;

import java.util.Arrays;
import java.util.List;

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.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

//切面类
@Component//容器管理
@Aspect//切面类 
@Order(1)
public class LogAspect {
	
	//定义公共切点
	@Pointcut("execution(* com.hanqi.test.I_jsq.*(..))")
	public  void pointCut()
	{
		
	}
	
	//前置通知@Before
	@Before("pointCut()")//引用公共切点
	public void beforeLog(JoinPoint jp)//通知  JoinPoint表示连接点
	{
		//连接点的方法名
		String ms = jp.getSignature().getName();
		
		//连接点方法的参数
		List<Object> ls = Arrays.asList(jp.getArgs());
		
		
		System.out.println("前置日志,方法名 = "+ms+" 参数列表= "+ls);
	}
	
	//后置通知
	@After("pointCut()")
	public void afterLog(JoinPoint jp)
	{
		//连接点的方法名
				String ms = jp.getSignature().getName();
				
				//连接点方法的参数列表
				List<Object> ls = Arrays.asList(jp.getArgs());
				
				
				System.out.println("后置日志,方法名 = "+ms+" 参数列表= "+ls);
	}
	
	//返回通知
	//@AfterReturning(pointcut="execution(* com.hanqi.test.I_jsq.*(..))" ,returning="rtn")
	@AfterReturning(pointcut="pointCut()" ,returning="rtn")
	public void returningLog(double rtn)
	{
		//接收返回值
		System.out.println("返回值="+rtn);
	}
	
	//异常通知
	@AfterThrowing(pointcut="pointCut()" , throwing="msg")
	public void errorLog(Exception msg)
	{
		System.out.println("异常通知="+msg.getMessage());
	}
	
	//环绕通知
	@Around("pointCut()")//切点表达式,第一个*表示返回类型,第二个*表示方法名
	public Object aroundLog(ProceedingJoinPoint pjp)
	{
		Object rtn= null;
		//连接点的方法名
		String ms = pjp.getSignature().getName();
		
		//连接点方法的参数
		List<Object> ls = Arrays.asList(pjp.getArgs());
		//实现四种通知
		//1.前置通知
		System.out.println("这是环绕通知的前置通知,方法名= "+ms+" 参数="+ls);
		
		
		//调用目标方法
		try {
			
			rtn= pjp.proceed();
			
			//3.返回通知
			System.out.println("这是环绕通知的返回通知,返回值="+rtn );
			
		} catch (Throwable e) {
			//4.异常通知
			System.out.println("这是环绕通知的异常通知,异常信息="+e.getMessage());
			e.printStackTrace();
		}
		finally
		{
			//2.后置通知
			System.out.println("这是环绕通知的后置通知");
		}
		
		
		return rtn;
	}
}
package com.hanqi.test;


import java.util.Arrays;
import java.util.List;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
	//	切面类
@Component
@Aspect
@Order(2)
public class CheckAspect {
	
	//前置通知
	//@Before("execution(* com.hanqi.test.Myjsq.div(double,double))")
	@Before("LogAspect.pointCut()")//重用切点表达式
	public void beforeCheck(JoinPoint jp)
	{
		//获取参数
		Object[] ob = jp.getArgs();
		
		if((Double.parseDouble(ob[1].toString()))== 0)
		{
			System.out.println("参数不能等于0");
			System.out.println("1=="+Double.parseDouble(ob[1].toString()));
			System.out.println("0=="+Double.parseDouble(ob[0].toString()));
		}
	}

}

  测试类

package com.hanqi.test;

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

public class TestMain {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		//I_jsq jsq1 = new Myjsq();
		
		
		ApplicationContext ac = 
				new ClassPathXmlApplicationContext("app.xml");
		
		I_jsq jsq1 =(I_jsq)ac.getBean("my1");//通过接口创建代理对象
		
		jsq1.add(123, 456);
		
		jsq1.div(200, 0);

	}

}

  

  

posted @ 2016-12-14 09:24  琢磨先生  阅读(256)  评论(0编辑  收藏  举报
AmazingCounters.com