• 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);
    
    	}
    
    }
    

      

      

  • 相关阅读:
    非控制台应用程序输出信息到输出面板
    使用token实现接口权限验证
    创建虚拟目录http://localhost:1780/失败,错误:无法访问iis元数据库。您没用足够的特权访问计算机上的IIS网站
    隐藏桌面的回收站
    本地电脑与远程服务器之间不能复制粘贴解决方法
    移动端使用控制台打印 vconsole
    npm无法安装node-sass的解决方法
    远程报:这可能是由于credssp加密oracle修正
    L2TP连接尝试失败,因为安全层在初始化与远程计算机的协商时遇到一个处理错误
    让一张图片居中在中间(代码片段)
  • 原文地址:https://www.cnblogs.com/liuyanzeng/p/6177971.html
Copyright © 2020-2023  润新知