Spring AOP的实现方式

Spring AOP常用的实现方式有以下三种:

1.实现Spring API的传统方式
2.@AspectJ注解驱动的切面
3.基于XML设置的纯POJO切面

Spring支持五种类型的通知:
Before(前)  org.apringframework.aop.MethodBeforeAdvice
After-returning(返回后) org.springframework.aop.AfterReturningAdvice
After-throwing(抛出后) org.springframework.aop.ThrowsAdvice
Arround(周围) org.aopaliance.intercept.MethodInterceptor
Introduction(引入) org.springframework.aop.IntroductionInterceptor

我们就以最常用的Before和After-returning为例,讲解以下这三种AOP的使用。

一.实现Spring API的传统方式

//接口
public interface IHello {
	public void hello(String name);
}

//实现类
public class HelloSpeaker implements IHello {
	public void hello(String name) {
		System.out.println("Hello, "+name);
	}
}

定义一个日志类,在hello执行前后打印日志

public class LogAdvice implements MethodBeforeAdvice, AfterReturningAdvice {
	public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {
		System.out.println("print log afterReturning ");
	}

	public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
		System.out.println("print log before ");
	}
}

Spring核心配置文件applicationContext.xml配置AOP

<bean id="helloSpeaker" class="com.zs.test.HelloSpeaker"/>

<bean id="logAdvice" class="com.zs.test.aopone.LogAdvice"/>
    
<bean id="helloProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
	<property name="proxyInterfaces" value="com.zs.test.IHello"></property>
	<property name="target" ref="helloSpeaker"></property>
	<property name="interceptorNames" value="logAdvice"></property>
</bean>

注:通过org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator可以简化xml配置。

测试类

public static void main( String[] args )
{
    ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    IHello helloProxy = (IHello)ctx.getBean("helloProxy");
    helloProxy.hello("tom");
}

二.更简单的方式,通过AspectJ提供的注解实现AOP

将LogAdvice修改为LogAspect

@Aspect
public class LogAspect {
    //@Pointcut("execution(* *.hello(..))")//Pointcut表达式
    @Pointcut("execution(* com.zs.test.IHello.*(..))")//Pointcut表达式
    public void helloPoint(){}//Pointcut签名
    
    @Before("helloPoint()")
    public void before(){
    	System.out.println("print log before ");
    }
    
    @AfterReturning("helloPoint()")
    public void afterReturning(){
    	System.out.println("print log afterReturning ");
    }
}

在上面的代码中定义了一个Pointcut,Pointcut的定义包括两部分:Pointcut表达式与Pointcut签名。在开发中可以将共用的一些Pointcut组织起来单独定义在一个类里面,供整个应用程序使用,使用时可以指定完整类名称加上Pointcut签名。

Spring配置文件applicationContext.xml中,使用<aop:aspectj-autoproxy/> 标签启用@Aspect的Annotation支持。

<bean id="helloSpeaker" class="com.zs.test.HelloSpeaker"/>

<bean id="logAspect" class="com.zs.test.aoptwo.LogAspect"/>
   
<aop:aspectj-autoproxy/>

测试类,注意这里直接获取的是helloSpeaker

public static void main( String[] args )
{
    ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    IHello helloSpeaker = (IHello)ctx.getBean("helloSpeaker");
    helloSpeaker.hello("tom");
}

三.基于XML设置的纯POJO切面

这种方式的LogAdvice不必耦合任何API,只是一个纯的POJO

public class LogAdvice{
	public void afterReturning() throws Throwable {
		System.out.println("print log afterReturning ");
	}

	public void before() throws Throwable {
		System.out.println("print log before ");
	}
}

配置文件

<bean id="helloSpeaker" class="com.zs.test.HelloSpeaker"/>

<bean id="logAdvice" class="com.zs.test.aopthree.LogAdvice"/>

<aop:config>
	<aop:aspect ref="logAdvice">
		<aop:before method="before" pointcut="execution(* *.hello(..))" />
		<aop:after method="afterReturning" pointcut="execution(* *.hello(..))" />
	</aop:aspect>
</aop:config>

另一种写法 

<aop:config>
	<aop:aspect ref="logAdvice">
		<aop:pointcut id="helloPoint" expression="execution(* *.hello(..))" />
		<aop:before method="before" pointcut-ref="helloPoint" />
		<aop:after method="afterReturning" pointcut-ref="helloPoint" />
	</aop:aspect>
</aop:config>

测试类,与上一个例子完全一样

public static void main( String[] args )
{
    ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    IHello helloSpeaker = (IHello)ctx.getBean("helloSpeaker");
    helloSpeaker.hello("tom");
}

 

不知不觉已到了2018年最后一个 月了,不知道年底前还能再做点什么?

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值