AOP实现(二)——Spring 2.0中的AOP实现

    Spring 2.0中,除了传统的通过实现AOP AIP的方式来实现Advice之外,还提供了两种更加简便的方式来实现Advice1)基于XML Schema的设置;2)基于Annotation的支持,采用这两种方式,Advice将不用实现特定的接口。现在让我们来看看如何使用这两种方式来分别实现Before AdviceAfter AdviceAround AdviceThrowing Advice
    一、Before Advice:基于
XML Schema
    当基于XML Schema实现Before Advice时,你的Advice类不用实现org.springframework.aop.MethodBeforeAdvice接口,例如:
java代码

package com.savage.aop;  
  
import org.aspectj.lang.JoinPoint;  
  
public class LogBeforeAdvice {  
    public void before(JoinPoint joinPoint) {  
        System.out.println("Logging before " + joinPoint.getSignature().getName());  
    }  
} 

    before
方法是在目标对象上的方法被执行前要执行的方法,before方法中的JoinPoint参数是可选项,你可以根据需要决定是否需要JoinPoint参数,通过JoinPoint对象,你可以获得目标对象(getTarget())、目标方法上的参数(getArgs())等信息。
   
然后在XML中为目标对象指定LogBeforeAdvice
代理:
xml 代码
<?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-2.0.xsd  
    http://www.springframework.org/schema/aop  
    http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">  
    <bean id="messageSender" class="com.savage.aop.HttpMessageSender"></bean>  
      
    <bean id="logBeforeAdvice" class="com.savage.aop.LogBeforeAdvice"></bean>  
      
    <aop:config>  
        <aop:aspect id="logBefore" ref="logBeforeAdvice">  
            <aop:before pointcut="execution(* com.savage.aop.MessageSender.*(..))" 
                        method="before"/>  
        </aop:aspect>  
    </aop:config>  
</beans>  

   
如上所示,在 Spring 2.0 中要使用基于 XML Sechma 声明 AOP 的方式,需要在 XML 中加入 aop 的名称空间。当基于 XML Sechma 实现 AOP 时,所有的 AOP 都是在 <aop:config></aop:config> 标签中声明的, <aop:aspect></aop:aspect> 用于定义 Advice 实例。 <aop:before></aop:before> 表示当前实例用于实现 Before Advice pointcut 属性用于指定 pointcut 表示式,上面的例子表示此 Advice 将应用于 com.savage.aop.MessageSender 接口中的任何方法; method 属性表示 Advice 上要调用的方法。
   
现在调用任何 MessageSender 接口上的方法之前都会执行 LogBeforeAdvice before 方法,例如:
java 代码
package com.savage.aop;  
  
import org.springframework.context.ApplicationContext;  
import org.springframework.context.support.ClassPathXmlApplicationContext;  
  
public class AdviceDemo {  
    public static void main(String[] args) {  
        ApplicationContext context = 
                           new ClassPathXmlApplicationContext("beans-config.xml");  
        MessageSender sender = (MessageSender)context.getBean("messageSender");  
        sender.sendMessage("message");  
    }  
}

    二、 Before Advice :基于 Annotation
    使用 Annotation 来实现 Advice ,在 XML 文件上的定义要比基于 XML Sechema 的方法要简便的多,但在实现 Before Advice 类时,则需要使用到 @Aspect @Before 标识,并需要引入 org.aspectj.lang.annotation 包中的类。还以 LogBeforeAdvice 为例, LogBeforeAdvice 类需要改为:
java 代码
package com.savage.aop;  
  
import org.aspectj.lang.JoinPoint;  
import org.aspectj.lang.annotation.Aspect;  
import org.aspectj.lang.annotation.Before;  
  
@Aspect  
public class LogBeforeAdvice {  
    @Before("execution(* com.savage.aop.MessageSender.*(..))")  
    public void before(JoinPoint joinPoint) {  
        System.out.println("Logging before " + joinPoint.getSignature().getName());  
    }  
}  


通过aop命名空间的 <aop:aspectj-autoproxy />声明自动为spring容器中那些配置@aspectJ切面的bean
创建代理,织入切面。当然,spring在内部依旧采用AnnotationAwareAspectJAutoProxyCreator进行自动代理的创建工作,但具体实现的细节已经被<aop:aspectj-autoproxy />隐藏起来了, <aop:aspectj-autoproxy />有一个proxy-target-class属性,默认为false,表示使用jdk动态代理织入增强,当配为<aop:aspectj-autoproxy  poxy-target-class="true"/>时,表示使用CGLib动态代理技术织入增强。不过即使proxy-target-class设置为false,如果目标类没有声明接口,则spring将自动使用CGLib动态代理。

    如上所示,通过
@Aspect 将一个类声明为 Aspect 类,通过 @Before 将方法声明 Before Advice ,方法中的 JoinPoint 同样是可选的。 然后在 XML 文件中做如下定义:
xml 代码
<?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-2.0.xsd  
    http://www.springframework.org/schema/aop  
    http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">  
    <bean id="messageSender" class="com.savage.aop.HttpMessageSender"></bean>  
      
    <bean id="logBeforeAdvice" class="com.savage.aop.LogBeforeAdvice"></bean>  
      
    <aop:aspectj-autoproxy/>  
</beans>

    所有基于
Annotation 实现的 Advice ,在 XML 文件中都只要使用 <aop:aspectj-autoproxy></aop:aspectj-autoproxy> 进行设置就可以了,非常简单。

    三、
After Advice :基于 XML Sechma
   
Before Advice 一样,基于 XML Sechma 实现 After Returning Advice 时,不再需要 org.springframework.aop.AfterReturningAdvice 接口:
java 代码
package com.savage.aop;  
  
import org.aspectj.lang.JoinPoint;  
  
public class LogAfterReturningAdvice {  
    public void afterReturning(JoinPoint joinPoint) {  
        System.out.println("Logging after " + joinPoint.getSignature().getName());  
    }  
}

    然后在 XML 中做如下设置:
xml 代码
<?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-2.0.xsd  
    http://www.springframework.org/schema/aop  
    http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">  
    <bean id="messageSender" class="com.savage.aop.HttpMessageSender"></bean>  
      
    <bean id="logAfterReturningAdvice" 
          class="com.savage.aop.LogAfterReturningAdvice"></bean>  
      
    <aop:config>  
        <aop:aspect id="logAfterReturning" ref="logAfterReturningAdvice">  
            <aop:after-returning   
                pointcut="execution(* com.savage.aop.MessageSender.*(..))"   
                method="afterReturning"/>  
        </aop:aspect>  
    </aop:config>  
</beans>

  四、
After Advice :基于 Annotation
   
Before Advice 相似,使用 @AfterReturning 来表示 After Returning Advice
java 代码
package com.savage.aop;  
  
import org.aspectj.lang.JoinPoint;  
import org.aspectj.lang.annotation.Aspect;  
import org.aspectj.lang.annotation.AfterReturning;  
  
@Aspect  
public class AfterReturningAdvice {  
    @AfterReturning(pointcut="execution(* com.savage.aop.MessageSender.*(..))", 
                    returning="retVal")  
    public void afterReturning(JoinPoint joinPoint, Object retVal) {  
        System.out.println("Logging after " + joinPoint.getSignature().getName());  
    }  
}

    这里和 Before Advice 有点不同的是,在定义 Poincut 表示式时,多了一个 returning 属性,用于指定目标方法执行完后的返回值。
   
XML 文件中的设置与 LogBeforeAdvice 的相似(将 logBeforeAdvice 的定义改为 logAfterReturning 的定义),不再列举。

  五、 Around Advice :基于 XML Sechma
   
Spring 2.0 中, Around Advice 不用实现 org.aoplliance.intercept.MethodInterceptor 接口,但 Advice 的方法必须返回对象,并且必须定义一个 ProceedingJoinPoint 参数,例如:
java 代码
package com.savage.aop;  
  
import org.aspectj.lang.ProceedingJoinPoint;  
  
public class LogAroundAdvice {  
    public Object invoke(ProceedingJoinPoint joinPoint) {  
        System.out.println("Logging before " + joinPoint.getSignature().getName());  
        Object retVal = joinPoint.proceed();  
        System.out.println("Logging after " + joinPoint.getSignature().getName());  
        return retVal;  
    }  
} 

    XML 中的设置如下:
    xml 代码
<?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-2.0.xsd  
    http://www.springframework.org/schema/aop  
    http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">  
    <bean id="messageSender" class="com.savage.aop.HttpMessageSender"></bean>  
      
    <bean id="logAroundAdvice" class="com.savage.aop.LogAroundAdvice"></bean>  
      
    <aop:config>  
        <aop:aspect id="logAround" ref="logAroundAdvice">  
            <aop:around   
                pointcut="execution(* com.savage.aop.MessageSender.*(..))"   
                method="invoke"/>  
        </aop:aspect>  
    </aop:config>  
</beans>

  六、 Around Advice :基于 Annotation
   
Before Advice 相似,使用 @Around 来表示 Around Advice
java 代码
package com.liuyoung.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class LogAroundAdvice {
	@Around("execution(* com.savage.aop.MessageSender.*(..))")
	public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable {
		System.out.println("Logging before [log around advice] : " + joinPoint.getSignature().getName());  
        Object retVal = joinPoint.proceed();  
        System.out.println("Logging after [log around advice] : " + joinPoint.getSignature().getName());  
        return retVal;
	}
}

  七、
Throw Advice :基于 XML Sechma
   
Spring 2.0 中, Throw Advice 不用实现 org.springframework.aop.ThrowsAdvice 接口,但 Advice 的方法必须定义 Throwable (或其子类)参数,例如:
java 代码
package com.savage.aop;  
  
import org.aspectj.lang.JoinPoint;  
  
public class LogThrowingAdvice {  
    public void afterThrowing (JoinPoint joinPoint, Throwable throwable) {  
        System.out.println("Logging when throwing " + joinPoint.getSignature().getName());  
    }  
} 

    在 XML 的设置如下:
    xml 代码
<?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-2.0.xsd  
    http://www.springframework.org/schema/aop  
    http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">  
    <bean id="messageSender" class="com.savage.aop.HttpMessageSender"></bean>  
      
    <bean id="logThrowingAdvice" class="com.savage.aop.LogThrowingAdvice"></bean>  
      
    <aop:config>  
        <aop:aspect id="logThrowing" ref="logThrowingAdvice">  
            <aop:after-throwing   
                pointcut="execution(* com.savage.aop.MessageSender.*(..))"  
                throwing="throwable"  
                method="afterThrowing"/>  
        </aop:aspect>  
    </aop:config>  
</beans>

    在 <aop:after-throwing></aop:after-throwing> 中必须定义 throwing 属性,指定方法中的 throwable 参数。 Spring 将根据异常类型决定是否调用 afterThrowing 方法。

 
八、 Throw Advice :基于 Annotation
java 代码
package com.savage.aop;  
  
import org.aspectj.lang.JoinPoint;  
import org.aspectj.lang.annotation.Aspect;  
import org.aspectj.lang.annotation.AfterThrowing;  
  
@Aspect  
public class AfterThrowingAdvice {  
    @AfterThrowing(pointcut="execution(* com.savage.aop.MessageSender.*(..))", 
                   throwing="throwable")  
    public void afterThrowing(JoinPoint joinPoint, Throwable throwable) {  
        System.out.println("Logging when throwing " 
                           + joinPoint.getSignature().getName());  
    }  
}










  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值