Spring----面向切面编程和通知类型

面向过程:算法+数据结构java

面向对象(OOP):对象+消息算法

面向接口:多态性spring

面向切面(AOP):把非业务逻辑的功能,提取出来,定义成一个一个的切面。当你的程序运行到这个切面后,自动完成这个切面的全部功能。apache

 

AOP简介

 前置通知数据结构

 切入点表达式app

//在applicationContext.xml文件中配置-----扫描带注解的包----表示使用动态代理测试

 编写一个切面类

 里面的注解@Before上的value值是切入点(哪一个类下的哪一个方法)spa

package com.aspect; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; //定义了日志切面 
@Aspect//表示这个类是一个切面
@Component//把普通法的pojo实例化到Spring容器中,至关于配置文件中的<bean id="" class=""/>
public class LoggingAspect { //前置通知===参数:切入点表达式--指定类的全部方法--括号里面是参数 //切入点为--该指定类且参数为Students的方法---也就是add方法
    @Before("execution(public * com.dao.impl.StudentsDAOImpl.* (com.entity.Students))") public void before(JoinPoint point){ System.out.println("before:"+point.getSignature().getName()+"("+point.getArgs()+")"); } }

在applicationContext.xml配置文件中添加相关标签

<!-- 表示使用注解 -->
    <context:annotation-config/>
    
    <!-- 表示使用动态代理 -->
    <aop:aspectj-autoproxy proxy-target-class="true"/>
    
    <!-- 扫描带注解的包 -->
    <context:component-scan base-package="com"/>

测试结果:----会在指定的dao层add方法以前切入这个方法执行

一辆汽车诞生啦... 一个学生建立啦... 执行了setName()方法 service层保存学生Students [sid=s0006, name=IU, gender=女, birthday=Wed Jul 15 00:00:00 GMT+08:00 1998, address=韩国首尔, car=Car [brand=BMW, color=黑色]] before:add([Ljava.lang.Object;@11cbbeb1) dao层保存学生Students [sid=s0006, name=IU, gender=女, birthday=Wed Jul 15 00:00:00 GMT+08:00 1998, address=韩国首尔, car=Car [brand=BMW, color=黑色]]

 后置通知

 

切点表达式解释

返回通知

异常通知3d

环绕通知

 AOP相关术语

使用日志log4j. properties

log4j.rootLogger=INFO,stdout,R log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout #Pattern to output the caller's file name and line number.
#log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n #Print the date in ISO 8601 format log4j.appender.stdout.layout.ConversionPattern=%d [%t] %-5p %c - %m%n log4j.appender.R=org.apache.log4j.RollingFileAppender log4j.appender.R.File=example.log log4j.appender.R.MaxFileSize=100KB # Keep one backup file log4j.appender.R.MaxBackupIndex=1 log4j.appender.R.layout=org.apache.log4j.PatternLayout log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n # Print only messages of level WARN or above in the package com.foo. # log4j.logger.com.foo=WARN

定义的日志切面(类)

package com.aspect; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; 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.springframework.stereotype.Component; //定义了日志切面 
@Aspect//表示这个类是一个切面
@Component//把普通法的pojo实例化到Spring容器中,至关于配置文件中的<bean id="" class=""/>
public class LoggingAspect { //建立一个日志对象
    private static Logger logger=LogManager.getLogger(LoggingAspect.class.getName()); //前置通知===参数:切入点表达式--指定类的全部方法--括号里面是参数 //切入点为--该指定类且参数为Students的方法---也就是add方法
    @Before("execution(public * com.dao.impl.StudentsDAOImpl.* (com.entity.Students))") public void before(JoinPoint point){ // System.out.println("before:"+point.getSignature().getName()+"("+point.getArgs()+")");
        System.out.println("前置日志信息:"+point.getSignature().getName()+""); logger.info("前置日志信息:"+point.getSignature().getName()+""); } //后置通知
    @After("execution(public * com.dao.impl.StudentsDAOImpl.* (com.entity.Students))") public void after(JoinPoint point){ System.out.println("后置日志信息:"+point.getSignature().getName()+""); logger.info("后置日志信息:"+point.getSignature().getName()+""); } //返回通知
    @AfterReturning(value="execution(public * com.dao.impl.StudentsDAOImpl.* (com.entity.Students))",returning="result") public void afterReturning(JoinPoint point,Object result){ System.out.println("返回通知:"+point.getSignature().getName()+"("+point.getArgs()+")"+",result:"+result); logger.info("返回通知:"+point.getSignature().getName()+"("+point.getArgs()+")"+",result:"+result); } //异常通知
    @AfterThrowing(value="execution(public * com.dao.impl.StudentsDAOImpl.* (com.entity.Students))",throwing="ex") public void afterThrowing(JoinPoint point,Exception ex){ System.out.println("异常通知:"+point.getSignature().getName()+"("+point.getArgs()+")"+",exception:"+ex); logger.info("异常通知:"+point.getSignature().getName()+"("+point.getArgs()+")"+",exception:"+ex); } //环绕通知
    @Around("execution(public * com.dao.impl.StudentsDAOImpl.* (com.entity.Students))") public Object around(ProceedingJoinPoint point) throws Throwable{ Object result=null; System.out.println("环绕通知以前要作的事情:"+point.getSignature().getName()); //在这个地方是有throws Throwable,以便在异常通知时,获取异常信息
            result=point.proceed(); System.out.println("环绕通知以后要作的事情:"+point.getSignature().getName()); return result; } }

applicationContext.xml文件:

<!-- 表示使用注解 -->
    <context:annotation-config/>
    
    <!-- 表示使用动态代理 -->
    <aop:aspectj-autoproxy proxy-target-class="true"/>
    
    <!-- 扫描带注解的包 -->
    <context:component-scan base-package="com"/>

测试而后会在控制台打印出日志,以及生成日志文件example.log文件。代理

相关文章
相关标签/搜索