网站开发项目总结模板,付费网站 源码 下载链接,网站建设请示报告,网站的建设和设计方案使用Spring的AOP 一、AOP 的常用注解1.切面类Aspect2.Pointcut3.前置通知Before4.后置通知AfterReturning5.环绕通知Around6.异常通知AfterThrowing7.最终通知After8.切面顺序Order9.启用自动代理EnableAspectJAutoProxy 二、AOP注解方式开发三、AOP 全注解开发四、基于XML配置… 使用Spring的AOP 一、AOP 的常用注解1.切面类Aspect2.Pointcut3.前置通知Before4.后置通知AfterReturning5.环绕通知Around6.异常通知AfterThrowing7.最终通知After8.切面顺序Order9.启用自动代理EnableAspectJAutoProxy 二、AOP注解方式开发三、AOP 全注解开发四、基于XML配置方式的AOP了解 Spring 对 AOP 的实现包括以下3种方式 第一种方式Spring框架结合AspectJ框架实现的AOP基于注解方式。第二种方式Spring框架结合AspectJ框架实现的AOP基于XML方式。第三种方式Spring框架自己实现的AOP基于XML方式。 实际开发种都是Spring AspectJ来实现的AOP。什么是AspectJEclipse组织的一个支持AOP的框架。AspectJ框架是独立于Spring框架之外的一个框架Spring框架用了AspectJAspectJ项目起源于帕洛阿尔托Palo Alto研究中心缩写为PARC。该中心由Xerox集团资助Gregor Kiczales领导从1997年开始致力于AspectJ的开发1998年第一次发布给外部用户2001年发布1.0 release。为了推动AspectJ技术和社团的发展PARC在2003年3月正式将AspectJ项目移交给了Eclipse组织因为AspectJ的发展和受关注程度大大超出了PARC的预期他们已经无力继续维持它的发展。 一、AOP 的常用注解
1.切面类Aspect Aspect作用是把当前类标识为一个切面供容器读取。 Retention(RetentionPolicy.RUNTIME)
Target({ElementType.TYPE})
public interface Aspect {String value() default ;
}2.Pointcut
Pointcut注解标注在方法上面用来定义切入点。可以这样做将切点表达式单独的定义出来在需要的位置引入即可。Retention(RetentionPolicy.RUNTIME)
Target({ElementType.METHOD})
public interface Pointcut {String value() default ;String argNames() default ;
}3.前置通知Before
Before目标方法执行之前的通知Retention(RetentionPolicy.RUNTIME)
Target({ElementType.METHOD})
public interface Before {String value();String argNames() default ;
}4.后置通知AfterReturning
AfterReturning目标方法执行之后的通知Retention(RetentionPolicy.RUNTIME)
Target({ElementType.METHOD})
public interface AfterReturning {String value() default ;String pointcut() default ;String returning() default ;String argNames() default ;
}5.环绕通知Around
Around目标方法之前添加通知同时目标方法执行之后添加通知。Retention(RetentionPolicy.RUNTIME)
Target({ElementType.METHOD})
public interface Around {String value();String argNames() default ;
}6.异常通知AfterThrowing
AfterThrowing发生异常之后执行的通知Retention(RetentionPolicy.RUNTIME)
Target({ElementType.METHOD})
public interface AfterThrowing {String value() default ;String pointcut() default ;String throwing() default ;String argNames() default ;
}7.最终通知After
After放在finally语句块中的通知Retention(RetentionPolicy.RUNTIME)
Target({ElementType.METHOD})
public interface After {String value();String argNames() default ;
}8.切面顺序Order
我们知道业务流程当中不一定只有一个切面可能有的切面控制事务有的记录日志有的进行安全控制如果多个切面的话顺序如何控制可以使用Order注解来标识切面类为Order注解的value指定一个整数型的数字数字越小优先级越高。Retention(RetentionPolicy.RUNTIME)
Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
Documented
public interface Order {/*** The order value.* pDefault is {link Ordered#LOWEST_PRECEDENCE}.* see Ordered#getOrder()*/int value() default Ordered.LOWEST_PRECEDENCE;
}9.启用自动代理EnableAspectJAutoProxy
开启自动代理之后凡事带有Aspect注解的bean都会生成代理对象。Target(ElementType.TYPE)
Retention(RetentionPolicy.RUNTIME)
Documented
Import(AspectJAutoProxyRegistrar.class)
public interface EnableAspectJAutoProxy {boolean proxyTargetClass() default false;boolean exposeProxy() default false;
}二、AOP注解方式开发 注意本文使用了 log4j2 日志如果不知道可以看我的博客 Spring对IoC的实现中的第一个Spring程序 注意本文也使用了 junit 进行单元测试。 使用SpringAspectJ的AOP需要引入的依赖如下 !--spring的核心依赖 aop core beans jcl expression 等--
dependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion6.1.4/version
/dependency
!-- AOP 依赖的AspectJ --
dependencygroupIdorg.springframework/groupIdartifactIdspring-aspects/artifactIdversion6.1.4/version
/dependencySpring配置文件中添加context命名空间和aop命名空间 ?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxmlns:aophttp://www.springframework.org/schema/aopxsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd/beans第一步定义目标类以及目标方法 package com.gdb.service;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;//目标类
Service
public class OrderService {private static final Logger logger LoggerFactory.getLogger(OrderService.class);//目标方法public void detail() {logger.info(正在打印订单详情......);}
}第二步编写切面类 package com.gdb.aspect;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;//切面类通知切点 切面
Aspect
Component
public class MyAspect {private static final Logger logger LoggerFactory.getLogger(MyAspect.class);//这是需要增强的代码通知Before(execution(* com.gdb.service..* (..))) // com.gdb.service包下的所有方法public void beforeAdvice() {logger.info(前置通知执行了);}AfterReturning(execution(* com.gdb.service..* (..))) // com.gdb.service包下的所有方法public void afterReturningAdvice() {logger.info(后置通知执行了);}Around(execution(* com.gdb.service..* (..))) // com.gdb.service包下的所有方法public void aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {logger.info(前置环绕通知执行了);proceedingJoinPoint.proceed(); // 执行目标方法logger.info(后置环绕通知执行了);}AfterThrowing(execution(* com.gdb.service..* (..))) // com.gdb.service包下的所有方法public void afterThrowingAdvice() {logger.info(异常通知执行了);}After(execution(* com.gdb.service..* (..))) // com.gdb.service包下的所有方法public void afterAdvice() {logger.info(最终通知执行了);}
}第三步在配置文件中启动包扫描启用自动代理 ?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxmlns:aophttp://www.springframework.org/schema/aopxsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd!--开启组件扫描--context:component-scan base-packagecom.gdb/!--开启自动代理--aop:aspectj-autoproxy proxy-target-classfalse/!--aop:aspectj-autoproxy proxy-target-classtrue/ 开启自动代理之后凡事带有Aspect注解的bean都会生成代理对象。proxy-target-classtrue 表示采用cglib动态代理。proxy-target-classfalse 表示采用jdk动态代理。默认值是false。即使写成false当没有接口的时候也会自动选择cglib生成代理类。--
/beans第四步编写测试程序 Test
public void test(){ApplicationContext applicationContext new ClassPathXmlApplicationContext(spring.xml);OrderService orderService applicationContext.getBean(orderService, OrderService.class);orderService.detail();
}第五步执行结果 通过上面的执行结果就可以判断他们的执行顺序了这里不再赘述。 第六步结果中没有异常通知这是因为目标程序执行过程中没有发生异常。我们尝试让目标方法发生异常 package com.gdb.service;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;Service
public class OrderService {private static final Logger logger LoggerFactory.getLogger(OrderService.class);public void detail() {logger.info(正在打印订单详情......);throw new RuntimeException();}
}第七步执行结果 通过测试得知当发生异常之后最终通知也会执行因为最终通知After会出现在finally语句块中。出现异常之后后置通知和环绕通知的结束部分不会执行。 优化使用切点表达式 上面编写的切面类的缺点是 第一切点表达式重复写了多次没有得到复用。第二如果要修改切点表达式需要修改多处难维护。 可以这样做将切点表达式单独的定义出来在需要的位置引入即可。 package com.gdb.aspect;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;Aspect
Component
public class MyAspect {private static final Logger logger LoggerFactory.getLogger(MyAspect.class);Pointcut(execution(* com.gdb.service..* (..)))public void pointcut() {}Before(pointcut()) // com.gdb.service包下的所有方法public void beforeAdvice() {logger.info(前置通知执行了);}AfterReturning(pointcut()) // com.gdb.service包下的所有方法public void afterReturningAdvice() {logger.info(后置通知执行了);}Around(pointcut()) // com.gdb.service包下的所有方法public void aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {logger.info(前置环绕通知执行了);proceedingJoinPoint.proceed();logger.info(后置环绕通知执行了);}AfterThrowing(pointcut()) // com.gdb.service包下的所有方法public void afterThrowingAdvice() {logger.info(异常通知执行了);}After(pointcut()) // com.gdb.service包下的所有方法public void afterAdvice() {logger.info(最终通知执行了);}
}使用Pointcut注解来定义独立的切点表达式。 注意这个Pointcut注解标注的方法随意只是起到一个能够让Pointcut注解编写的位置。 三、AOP 全注解开发
第一步就是编写一个类在这个类上面使用大量注解来代替spring的配置文件spring配置文件消失了如下package com.gdb.config;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;Configuration // 配置类
ComponentScan(com.gdb)
EnableAspectJAutoProxy(proxyTargetClass false)
public class SpringConfig {
}第二步测试程序也变化了Test
public void test() {AnnotationConfigApplicationContext applicationContext new AnnotationConfigApplicationContext(SpringConfig.class);OrderService orderService applicationContext.getBean(orderService, OrderService.class);orderService.detail();
}第三步执行结果 四、基于XML配置方式的AOP了解
第一步编写目标类
package com.gdb.service;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class OrderService {private static final Logger logger LoggerFactory.getLogger(OrderService.class);public void detail() {logger.info(正在打印订单详情......);}
}第二步编写切面类并且编写通知
package com.gdb.aspect;import org.aspectj.lang.ProceedingJoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class MyAspect {private static final Logger logger LoggerFactory.getLogger(MyAspect.class);public void beforeAdvice() {logger.info(前置通知执行了);}public void afterReturningAdvice() {logger.info(后置通知执行了);}public void aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {logger.info(前置环绕通知执行了);proceedingJoinPoint.proceed();logger.info(后置环绕通知执行了);}public void afterThrowingAdvice() {logger.info(异常通知执行了);}public void afterAdvice() {logger.info(最终通知执行了);}
}第三步编写spring配置文件
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxmlns:aophttp://www.springframework.org/schema/aopxsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsdbean idmyAspect classcom.gdb.aspect.MyAspect/bean idorderService classcom.gdb.service.OrderService/!--aop配置--aop:config!--切点表达式--aop:pointcut idp expressionexecution(* com.gdb.service..* (..))/!--切面--aop:aspect refmyAspect!--切面通知 切点--aop:before methodbeforeAdvice pointcut-refp/aop:after-returning methodafterReturningAdvice pointcut-refp/aop:around methodaroundAdvice pointcut-refp/aop:after-throwing methodafterThrowingAdvice pointcut-refp/aop:after methodafterAdvice pointcut-refp//aop:aspect/aop:config
/beans第四步编写测试程序
Test
public void test() {ClassPathXmlApplicationContext applicationContext new ClassPathXmlApplicationContext(spring.xml);OrderService orderService applicationContext.getBean(orderService, OrderService.class);orderService.detail();
}第四步执行结果 通过结果可以看出来顺序和前面的不一样了我感觉是配置文件中的顺序有关系由于主要都是使用注解的方式。