您的位置:首页 > 编程语言 > Java开发

Spring AOP之Advice

2015-07-17 11:00 465 查看
Spring AOP之Advice

   前置通知:即代码被执行之前被调用
   后置通知:即代码执行之后进行调用
   环绕通知:即代码执行前后进行调用
这两种方式的实现方式用到了动态代理的思想来完成的,
总结不想说废话:
首先是Spring1.x对Advice的支持:

 
public interface IHello {
public void sayHello1() ;
public void sayHello2() ;
public void sayHello3() ;
public void sayHello4() ;
}

 然后就是类的实现:

package com.spring.test;

public class Hello implements IHello{

public void sayHello1() {
System.out.println("111111111111");
}

public void sayHello2() {
System.out.println("222222222222");
}

public void sayHello3() {
System.out.println("333333333333");
}

public void sayHello4() {
System.out.println("444444444444");
}
}

 
然后是负责前置通知的类,要实现MethodBeforeAdvice接口:

 

 
 
public class AdviceBeforeHello implements MethodBeforeAdvice {
@Override
public void before(Method arg0, Object[] arg1, Object arg2)
throws Throwable {
System.out.println("验证用户。。。。");

}
}

 然后是负责后置通知的类,要实现AfterReturningAdvice接口:

 

 
public class AdviceAfterHello implements AfterReturningAdvice{

@Override
public void afterReturning(Object arg0, Method arg1, Object[] arg2,
Object arg3) throws Throwable {
System.out.println("方法执行完毕");

}

}

 

 

 
配置项:
<bean id="beforeHello" class="com.spring.advice.AdviceBeforeHello" />
<bean id="afterHello" class="com.spring.advice.AdviceAfterHello"></bean>
<bean id="hello" class="com.spring.test.Hello"></bean>
<!-- 注册代理类 -->
<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>com.spring.test.IHello</value>
</property>

<!-- 目标对象,即Hello对象 -->
<property name="target" ref="hello"></property>
<!-- 应用的前置通知,拦截器名称 -->
<property name="interceptorNames">
<list>
<value>beforeHello</value>
<value>afterHello</value>

</list>
</property>
</bean>

 

 

测试方法:
 
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
IHello hello = (IHello) context.getBean("proxy");
hello.sayHello1();
hello.sayHello2();
hello.sayHello3();
hello.sayHello4();

 

 

结果:



 
下面是环绕通知:
public class AdviceAroundHello implements MethodInterceptor{

@Override
public Object invoke(MethodInvocation arg0) throws Throwable {
Object object=null;
System.out.println("验证用户");
try {
object=arg0.proceed();
} finally{
System.out.println("方法执行完毕");
}

return object;
}

}

 然后配置beans.xml:
<bean id="aroundHello" class="com.spring.advice.AdviceAroundHello"></bean>

<bean id="hello" class="com.spring.test.Hello"></bean>
<!-- 注册代理类 -->
<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>com.spring.test.IHello</value>
</property>

<!-- 目标对象,即Hello对象 -->
<property name="target" ref="hello"></property>
<!-- 应用的前置通知,拦截器名称 -->
<property name="interceptorNames">
<list>
<value>aroundHello</value>
</list>
</property>
</bean>

 
 以上是Spring1.x对AOP的支持,,Spring2.x除了支持Spring1.x外,还提供了两种实现AOP的方式:
1.基于XML的配置,使用基于Schema的XML配置来完成AOP而且Advice也不用再实现任何其他特定接口。
2.使用JDK5的注释来完成AOP的实现,只需要一个简单的标签就可以完成AOP的整个过程。
 
基于XML Schema的前置通知配置如下:
   编写通知的逻辑代码:
public class AdviceBeforeHello {
public void beforeHello(){
System.out.println("验证用户。。。。");

}
}

 在beans.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.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <!-- 注册接口实现类 -->
<bean id="hello" class="com.spring.test.Hello"></bean>
<aop:config>
<!--  -->
<aop:pointcut id="beforePointCut"
expression="execution(* com.spring.test.IHello.*(..))" />
<aop:aspect id="before" ref="beforeAdvice">
<aop:before method="beforeHello" pointcut-ref="beforePointCut" />
</aop:aspect>
</aop:config>

<bean id="beforeAdvice" class="com.spring.advice.AdviceBeforeHello"></bean>
</beans>

 其他不变。。。。
 
 
2.基于Annotation的前置通知:
切面类:
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class AdviceBeforeHello {
@Before("execution(*  com.spring.test.IHello.*(..))")
public void beforeHello(){
System.out.println("验证用户。。。。");

}
}

 beans.xml配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns
4000
="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.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <!-- 注册接口实现类 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<bean id="hello" class="com.spring.test.Hello"></bean>
<bean id="beforeAdvice" class="com.spring.advice.AdviceBeforeHello"></bean>
</beans>

 
 基于XML和Annotation的后置通知和前置通知类似。下面是基于XML的环绕通知:
 
import org.aspectj.lang.ProceedingJoinPoint;

public class AdviceAroundHello {

public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("验证用户");
//执行连接点的方法
Object object = joinPoint.proceed();
System.out.println("方法执行完毕");
return object;
}

}

 
 beans.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.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <!-- 注册接口实现类 -->
<bean id="hello" class="com.spring.test.Hello"></bean>
<aop:config>
<aop:pointcut id="aroundPointcut"
expression="execution(*  com.spring.test.IHello.*(..))" />
<aop:aspect id="around" ref="aroundAdvice">
<aop:around method="around" pointcut-ref="aroundPointcut" />
</aop:aspect>
</aop:config>

<bean id="aroundAdvice" class="com.spring.advice.AdviceAroundHello"></bean>
</beans>

 
 其他不变。
 
-------------------------------------------------------------------------------------------------------------------------------
基于Annotation的环绕通知:
package com.spring.advice;

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

@Aspect
public class AdviceAroundHello {
@Around("execution(*  com.spring.test.IHello.*(..))")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("验证用户");
// 执行连接点的方法
Object object = joinPoint.proceed();
System.out.println("方法执行完毕");
return object;
}

}

 beans.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.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <!-- 注册接口实现类 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

<bean id="hello" class="com.spring.test.Hello"></bean>
<bean id="aroundAdvice" class="com.spring.advice.AdviceAroundHello"></bean>
</beans>

 
完成!!
 
 
 
 





大小: 51.1 KB

查看图片附件
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: