深入浅出Spring AOP
来源:互联网 发布:手机编程工具排行榜 编辑:程序博客网 时间:2024/06/01 19:26
AOP联盟规范了一套用于规范AOP实现的底层API,通过这些统一的底层API,可以使得各个AOP实现及工具产品之间实现相互移植。这些API主要以标准接口的形式提供,是AOP编程思想所要解决的横切交叉关注点问题各部件的最高抽象。无论是Spring的AOP框架,还是开源的aspect框架,都是直接以这些API为基础所构建。
Spring实现AOP都是基于接口形式的
- public interface GreetingInterface {
- String sayHello(String name);
- }
- public class GreetingImpl implements GreetingInterface {
- @Override
- public String sayHello(String name) {
- System.out.println("Hello! " + name);
- return name;
- }
- }
- /** 前置通知 */
- public class GreetingBeforeAdvice implements MethodBeforeAdvice{
- @Override
- public void before(Method method, Object[] args, Object target) throws Throwable {
- System.out.println(">>>>>>>>>>>>>>>>>>Before Start>>>>>>>>>>>>>>>>>>");
- System.out.println("Method Name: " + method.getName());
- System.out.println("args:" + Arrays.toString(args));
- System.out.println("Target : " + target.getClass().getName());
- System.out.println("<<<<<<<<<<<<<<<<<<Before End<<<<<<<<<<<<<<<<<<<<<<<<");
- }
- }
- /** 后置返回通知*/
- public class GreetingAfterAdvice implements AfterReturningAdvice {
- @Override
- public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
- System.out.println(">>>>>>>>>>>>>>>>After Start>>>>>>>>>>>>>>>>>>>>");
- System.out.println("returnValue:" + returnValue);
- System.out.println("Method Name: " + method.getName());
- System.out.println("args:" + Arrays.toString(args));
- System.out.println("Target : " + target.getClass().getName());
- System.out.println("<<<<<<<<<<<<<<<<<After End<<<<<<<<<<<<<<<<<<<<<<");
- }
- }
- /** 异常通知 */
- public class GreetingThrowAdvice implements ThrowsAdvice {
- public void afterThrowing(Method method, Object[] args, Object target, Exception e) {
- System.out.println("---------- Throw Exception ----------");
- System.out.println("Target Class: " + target.getClass().getName());
- System.out.println("Method Name: " + method.getName());
- System.out.println("Exception Message: " + e.getMessage());
- System.out.println("-------------------------------------");
- }
- }
- /** 环绕通知*/
- public class GreetingAroundAdvice implements MethodInterceptor {
- @Override
- public Object invoke(MethodInvocation invocation) throws Throwable {
- before();
- Object result = invocation.proceed();
- after();
- return result;
- }
- private void before() {
- System.out.println("---->>>>Before");
- }
- private void after() {
- System.out.println("---->>>>After");
- }
- }
- public class AdviceClient {
- public static void main(String[] args) {
- ProxyFactory proxyFactory = new ProxyFactory(); // 创建代理工厂
- proxyFactory.setTarget(new GreetingImpl()); // 射入目标类对象
- proxyFactory.addAdvice(new GreetingBeforeAdvice()); // 添加前置通知
- proxyFactory.addAdvice(new GreetingAfterAdvice()); // 添加后置通知
- proxyFactory.addAdvice(new GreetingAroundAdvice()); // 添加环绕通知
- proxyFactory.addAdvice(new GreetingThrowAdvice()); // 添加抛出通知
- proxyFactory.setOptimize(true);//使用CGLIB动态代理
- GreetingInterface greeting = (GreetingInterface) proxyFactory.getProxy(); // 从代理工厂中获取代理
- greeting.sayHello("Jack"); // 调用代理的方法
- }
- }
第一种方式:
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
- <bean id="greetingAfterReturningAdvice" class="com.somnus.spring.xml.aop.GreetingAfterReturningAdvice"/>
- <bean id="greetingAroundAdvice" class="com.somnus.spring.xml.aop.GreetingAroundAdvice"/>
- <bean id="greetingBeforeAdvice" class="com.somnus.spring.xml.aop.GreetingBeforeAdvice"/>
- <bean id="greetingThrowsAdvice" class="com.somnus.spring.xml.aop.GreetingThrowsAdvice"/>
- <bean id="greetingImpl" class="com.somnus.spring.xml.aop.GreetingImpl"/>
- <!-- 配置一个代理 -->
- <bean id="greetingProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
- <property name="interfaces" value="com.somnus.spring.xml.aop.GreetingInterface"/> <!-- 需要代理的接口 -->
- <property name="target" ref="greetingImpl"/> <!-- 目标接口实现类 -->
- <property name="interceptorNames"> <!-- 拦截器名称(也就是增强类名称,Spring Bean 的 id) -->
- <list>
- <value>greetingBeforeAdvice</value>
- <value>greetingAfterReturningAdvice</value>
- </list>
- </property>
- </bean>
- </beans>
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
- <bean id="greetingIntroAdvice" class="com.somnus.spring.xml.aop.GreetingIntroAdvice"/>
- <bean id="greetingImpl" class="com.somnus.spring.xml.aop.GreetingImpl"/>
- <bean id="greetingImply" class="com.somnus.spring.xml.aop.GreetingImply"/>
- <!-- 使用ProxyFactoryBean或者其它IOC相关类来创建AOP代理的最重要好处就是通知切入点也可以由IOC来管理 -->
- <!-- 被代理类没有任何接口,使用CGLIB代理,否则JDK代理 -->
- <!-- 通过设置proxyTargetClass为true,可【强制使】用CGLIB -->
- <!-- 如果目标类实现了一个(或者多个)接口,那么创建代理的类型将依赖ProxyFactoryBean的配置 -->
- <!-- 如果ProxyFactoryBean的proxyInterfaces属性被设置为一个或者多个全限定接口名,基于JDK的代理将被创建 -->
- <!-- 如果ProxyFactoryBean的proxyInterfaces属性没有被设置,但是目标类实现了一个(或者更多)接口,那么ProxyFactoryBean将自动检测到这个目标类已经实现了至少一个接口,创建一个基于JDK的代理 -->
- <bean id="greetingProxy2" class="org.springframework.aop.framework.ProxyFactoryBean">
- <property name="interfaces" value="com.somnus.spring.xml.aop.Apology"/><!-- 需要动态实现的接口 -->
- <property name="target" ref="greetingImpl"/> <!-- 目标类 -->
- <property name="interceptorNames" value="greetingIntroAdvice"/> <!-- 引入增强 -->
- <property name="proxyTargetClass" value="true"/> <!-- 代理目标类(默认为 false,代理接口) -->
- </bean>
- </beans>
第二种方式:
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
- <bean id="greetingAfterReturningAdvice" class="com.somnus.spring.xml.aop.GreetingAfterReturningAdvice"/>
- <bean id="greetingAroundAdvice" class="com.somnus.spring.xml.aop.GreetingAroundAdvice"/>
- <bean id="greetingBeforeAdvice" class="com.somnus.spring.xml.aop.GreetingBeforeAdvice"/>
- <bean id="greetingThrowsAdvice" class="com.somnus.spring.xml.aop.GreetingThrowsAdvice"/>
- <bean id="greetingImpl" class="com.somnus.spring.xml.aop.GreetingImpl"/>
- <!-- 配置一个切面 -->
- <bean id="greetingAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
- <property name="advice" ref="greetingAroundAdvice"/> <!-- 增强 -->
- <property name="pattern" value="com.somnus.spring.xml.aop.GreetingImpl.good.*"/> <!-- 切点(正则表达式) -->
- </bean>
- <!-- 配置一个代理 -->
- <bean id="greetingProxy3" class="org.springframework.aop.framework.ProxyFactoryBean">
- <property name="interfaces" value="com.somnus.spring.xml.aop.GreetingInterface"/> <!-- 需要代理的接口 -->
- <property name="target" ref="greetingImpl"/> <!-- 目标接口实现类 -->
- <property name="interceptorNames" value="greetingAdvisor"/> <!-- 切面 -->
- <property name="proxyTargetClass" value="false"/> <!-- 代理目标类(默认为 false,代理接口)-->
- </bean>
- </beans>
第三种方式
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
- <bean id="greetingAfterReturningAdvice" class="com.somnus.spring.xml.aop.GreetingAfterReturningAdvice"/>
- <bean id="greetingAroundAdvice" class="com.somnus.spring.xml.aop.GreetingAroundAdvice"/>
- <bean id="greetingBeforeAdvice" class="com.somnus.spring.xml.aop.GreetingBeforeAdvice"/>
- <bean id="greetingThrowsAdvice" class="com.somnus.spring.xml.aop.GreetingThrowsAdvice"/>
- <bean id="greetingImpl" class="com.somnus.spring.xml.aop.GreetingImpl"/>
- <bean id="greetingImply" class="com.somnus.spring.xml.aop.GreetingImply"/>
- <!-- 自动代理(扫描 Bean名称) -->
- <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> -->
- <property name="beanNames" value="*Impl"/> <!-- 只为后缀是“Impl”的 Bean 生成代理 -->
- <property name="interceptorNames" value="greetingAroundAdvice"/> <!-- 增强 -->
- <property name="optimize" value="true"/> <!-- 是否对代理生成策略进行优化 -->
- </bean>
- <!-- optimize若为 true 时,则可对代理生成策略进行优化(默认是 false 的)。也就是说,如果该类有接口,
- 就代理接口(使用 JDK 动态代理);如果没有接口,就代理类(使用 CGLib 动态代理)。
- 而并非像之前使用的 proxyTargetClass 属性那样,强制代理类,而不考虑代理接口的方式。
- -->
- </beans>
- package com.somnus.spring.namespace.aop;
- import java.util.Arrays;
- import org.aspectj.lang.JoinPoint;
- import org.aspectj.lang.ProceedingJoinPoint;
- import org.aspectj.lang.reflect.MethodSignature;
- public class GreetAspector {
- /**@前置通知
- * 方法开始之前执行一段代码
- * @param joinPoint
- */
- public void before(JoinPoint joinPoint) {
- String methodName = joinPoint.getSignature().getName();
- Object[] args = joinPoint.getArgs();
- System.out.println("The method 【" + methodName + "】 begins with " + Arrays.asList(args));
- }
- /**@后置最终通知
- * 方法执行之后执行一段代码
- * 无论该方法是否出现异常
- * @param joinPoint
- */
- public void after(JoinPoint joinPoint) {
- String methodName = joinPoint.getSignature().getName();
- Object[] args = joinPoint.getArgs();
- System.out.println("The method 【" + methodName + "】 ends with " + Arrays.asList(args));
- }
- /**@后置返回通知
- * 方法正常结束后执行的代码,不包括抛出异常的情况
- * 返回通知是可以访问到方法的返回值的
- * @param joinPoint
- * @param result
- */
- public void afterReturning(JoinPoint joinPoint,Object result) {
- String methodName = joinPoint.getSignature().getName();
- System.out.println("The method 【" + methodName + "】 return with " + result);
- }
- /**@后置异常通知
- * 在方法出现异常时会执行的代码
- * 可以访问到异常对象,可以指定在出现特定异常时在执行通知代码
- * @param joinPoint
- * @param ex
- */
- public void afterThrowing(JoinPoint joinPoint, Exception ex) {
- String methodName = joinPoint.getSignature().getName();
- System.out.println("The method " + methodName + " occurs exception: " + ex);
- }
- /**@环绕通知
- * 环绕通知需要携带ProceedingJoinPoint类型的参数
- * 环绕通知类似于动态代理的全过程:ProceedingJoinPoint类型的参数可以决定是否执行目标方法。
- * 而且环绕通知必须有返回值,返回值即为目标方法的返回值
- * @param pjp
- * @return
- * @throws Throwable
- */
- public Object around(ProceedingJoinPoint pjp) throws Throwable {
- Object result = null;
- System.out.println("target:"+pjp.getTarget());
- MethodSignature signature = (MethodSignature) pjp.getSignature();
- String methodName = signature.getName();
- //执行目标方法
- try {
- System.out.println("ARROUND-->The method 【" + methodName + "】 begins with 【" + Arrays.asList(pjp.getArgs()) +"】");
- result = pjp.proceed();
- } catch (Throwable e) {
- System.out.println("ARROUND-->The method 【" + methodName + "】 occurs expection : 【" + e +"】");
- throw new RuntimeException(e);
- }
- System.out.println("ARROUND-->The method 【" + methodName + "】 return with 【" + result +"】");
- return result;
- }
- }
- <?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: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.xsd">
- <!-- application 上下文 -->
- <bean class="com.somnus.ApplicationContextHolder"/>
- <bean id="greetAspector" class="com.somnus.spring.namespace.aop.GreetAspector"/>
- <bean id="greetingImpl" class="com.somnus.spring.namespace.aop.GreetingImpl"/>
- <!-- AOP配置 -->
- <aop:config>
- <!-- 声明一个切面,并注入切面Bean,相当于@Aspect -->
- <aop:aspect id="greetAspector" ref="greetAspector">
- <!-- 配置一个切入点,相当于@Pointcut -->
- <aop:pointcut id="greetPointcut" expression="execution(* com.somnus.spring.namespace.aop.GreetingImpl.*(..))" />
- <!-- 配置通知,相当于@Before、@After、@AfterReturn、@Around、@AfterThrowing -->
- <aop:before pointcut-ref="greetPointcut" method="before"/>
- <aop:after pointcut-ref="greetPointcut" method="after"/>
- <aop:after-returning pointcut-ref="greetPointcut" method="afterReturning" returning="result"/>
- <aop:after-throwing pointcut-ref="greetPointcut" method="afterThrowing" throwing="ex"/>
- <aop:around pointcut-ref="greetPointcut" method="around"/>
- <aop:declare-parents types-matching="com.somnus.spring.namespace.aop.GreetingImpl"
- implement-interface="com.somnus.spring.namespace.aop.Apology"
- default-impl="com.somnus.spring.namespace.aop.ApologyImpl"/>
- </aop:aspect>
- </aop:config>
- </beans>
- <!-- 强制CGLIB代理 -->
- <!-- proxy-target-class属性,默认为false,表示使用jdk动态代理织入增强,当配为true时,
- 表示使用CGLib动态代理技术织入增强。不过即使proxy-target-class设置为false,如果目标类没有声明接口,
- 则spring将自动使用CGLib动态代理。@see http://blog.chinaunix.net/uid-11898547-id-3417894.html -->
- <aop:aspectj-autoproxy proxy-target-class="true"/>
- package com.somnus.spring.annotation.aop;
- import java.lang.reflect.Method;
- import java.util.Arrays;
- 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.DeclareParents;
- import org.aspectj.lang.reflect.MethodSignature;
- import org.springframework.stereotype.Component;
- @Aspect
- @Component
- public class GreetAspector {
- /**@前置通知
- * 方法开始之前执行一段代码
- * @param joinPoint
- */
- @Before("execution(* com.somnus.spring.annotation.aop.GreetingImpl.*(..))")
- public void before(JoinPoint point) {
- String methodName = point.getSignature().getName();
- Method method = ((MethodSignature) point.getSignature()).getMethod();
- System.out.println(method.getName());
- Object[] args = point.getArgs();
- System.out.println("The method 【" + methodName + "】 begins with " + Arrays.asList(args));
- }
- /**@后置最终通知
- * 方法执行之后执行一段代码
- * 无论该方法是否出现异常
- * @param joinPoint
- */
- @After("execution(* com.somnus.spring.annotation.aop.GreetingImpl.*(..))")
- public void after(JoinPoint point) {
- String methodName = point.getSignature().getName();
- Object[] args = point.getArgs();
- System.out.println("The method 【" + methodName + "】 ends with " + Arrays.asList(args));
- }
- /**@后置返回通知
- * 方法正常结束后执行的代码,不包括抛出异常的情况
- * 返回通知是可以访问到方法的返回值的
- * @param joinPoint
- * @param result
- */
- @AfterReturning(value="execution(* com.somnus.spring.annotation.aop.GreetingImpl.*(..))",returning="result")
- public void afterReturning(JoinPoint point,Object result) {
- String methodName = point.getSignature().getName();
- System.out.println("The method 【" + methodName + "】 return with " + result);
- }
- /**@后置异常通知
- * 在方法出现异常时会执行的代码
- * 可以访问到异常对象,可以指定在出现特定异常时在执行通知代码
- * @param joinPoint
- * @param ex
- */
- @AfterThrowing(value="execution(* com.somnus.spring.annotation.aop.GreetingImpl.*(..))", throwing="ex")
- public void afterThrowing(JoinPoint point, Exception ex) {
- String methodName = point.getSignature().getName();
- System.out.println("The method " + methodName + " occurs exception: " + ex);
- }
- /**@环绕通知
- * 环绕通知需要携带ProceedingJoinPoint类型的参数
- * 环绕通知类似于动态代理的全过程:ProceedingJoinPoint类型的参数可以决定是否执行目标方法。
- * 而且环绕通知必须有返回值,返回值即为目标方法的返回值
- * @param pjp
- * @return
- * @throws Throwable
- */
- @Around("execution(* com.somnus.spring.annotation.aop.GreetingImpl.*(..))")
- public Object around(ProceedingJoinPoint point) throws Throwable {
- Object result = null;
- System.out.println("target:" + point.getTarget());
- Method method = ((MethodSignature) point.getSignature()).getMethod();
- System.out.println(method.getName());
- String methodName = point.getSignature().getName();
- //执行目标方法
- try {
- //前置通知
- System.out.println("ARROUND-->The method 【" + methodName + "】 begins with 【" + Arrays.asList(point.getArgs()) +"】");
- result = point.proceed();
- } catch (Throwable e) {
- //后置异常通知【在方法出现异常时会执行的代码】
- System.out.println("ARROUND-->The method 【" + methodName + "】 occurs expection : 【" + e +"】");
- throw new RuntimeException(e);
- }
- //后置返回通知【方法正常结束后执行的代码,不包括抛出异常的情况】
- System.out.println("ARROUND-->The method 【" + methodName + "】 return with 【" + result +"】");
- return result;
- }
- /**
- * 用 AOP 的行话来讲,对方法的增强叫做 Weaving(织入),
- * 而对类的增强叫做 Introduction(引入)。
- * 而 Introduction Advice(引入增强)就是对类的功能增强,
- * 它也是 Spring AOP 提供的最后一种增强
- */
- @DeclareParents(value = "com.somnus.spring.annotation.aop.GreetingImpl", defaultImpl = ApologyImpl.class)
- private Apology apology;
- }
阅读全文
0 0
- 深入浅出 spring AOP 刑红瑞
- 深入浅出Spring AOP
- 深入浅出Spring Aop
- 深入浅出Spring(三) AOP详解
- 深入浅出Spring(三) AOP详解
- 深入浅出Spring之第三章AOP
- 深入浅出Spring(二) AOP详解
- Spring源码分析-深入浅出AOP(图文分析)
- 深入浅出AOP(一)
- 深入浅出Spring
- 【免费】深入浅出解读 Spring 源码:IOC/AOP 篇 | Chat · 预告
- AOP、Spring的AOP
- AOP--Spring AOP
- Spring AOP 嵌套AOP
- spring AOP
- Spring AOP
- Spring AOP
- spring aop
- 《甄嬛传》解读--后宫女人的心酸血泪史之腹黑学
- Java——完全背包
- one_exercise
- 算是做出决定
- Java并发之synchronized机制(wait和notify)
- 深入浅出Spring AOP
- hiho一下 第157周 二进制小数
- F1V3.0-图形-绘图类库快速搭建一个页面绘图应用实例
- USACO Section 1.1 Broken Necklace
- GSON
- 小结
- 【转】HTTP传输二进制 数据编码解码
- ZooKeeper源码分析
- c#中ArrayList 与string 、string[]的转换