AOP实现(二)---Spring框架中的AOP应用
2011-12-24 10:21
253 查看
一:传统方式(Spring1.0)
使用Spring中的AOP API中定义的接口来定义Adivce(通知,做什么事情),并设置代理对象(配置文件中使用org.springframework.aop.framework.ProxyFactoryBean)然后在程序中使用这个代理对象。
还有基于XML配置方式和注解方式。
1.方法前通知,实现接口MethodBeforeAdivce
2.被代理对象实现的接口
3.被代理对象
4.配置文件
配置文件中<property name="interceptorNames">下的<list>子标签也可以用
<idref local='interceptorLogin2'/>
5.测试
运行结果:
另外还有方法后通知,实现AfterReturingAdvice.它仅在方法正常返回后被调用,若方法执行中出现异常则不被调用。它可以看到方法的返回值,却不能改变它,由返回类型是void也可以知道。
环绕型通知,实现org.aopalliance.intercept.MethodInterceptor(aop联盟定义的,便于在实现规范的aop中迁移)
注意返回值是Object类型,如果希望不影响返回值,应当返回原方法的返回值,即
invocation参数中封装了原方法的信息,有getMethod(),getArguments()等方法。
异常通知ThrowsAdvice,此接口为标签接口,可以自定义方法名称,只要是如下形式
aferThrowing([Method],[args],[target],Throwable的子类)
二 XML文件的方式
1.引入AOP命名空间
2.建立目标对象,自定义的切面对象(不需要实现任何接口)
3.定义切入点,使用切入点表达式语言
4.配置xml文件
5.测试
三:使用注解的方式
在Spring的配置文件中引入aop命名空间
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation中加入
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
1.打开注解方式的配置项
注解本身不能干活,需要处理器
使用<aop:aspectj-autoproxy/> 提供对注解的解释功能。
2.定义切面、切入点(对业务Bean里面的哪些方法进行拦截),定义通知(拦截到方法以后所要做的工作)。
业务接口和业务方法如下:
定义切面,使用@Aspect注解,前提是把该切面交给Spring来管理,否则注解没有任何作用。
定义切入点,使用切入点表达式,形如如下形式:
execution表示运行时,后面是[返回值]+空格+包名.类名(包名..类名则表示连同子包)+点号+方法+(..)
注意:方法(..)表示方法的参数任意,*可以表示任意
切入点的名称定义是以一个方法的形式。名称连括号也带上。
定义通知
根据所作的工作是方法的前后位置,有不同的通知。
3.最后把切面和业务Bean都在xml配置文件中配置,交给Spring容器管理。
使用Spring中的AOP API中定义的接口来定义Adivce(通知,做什么事情),并设置代理对象(配置文件中使用org.springframework.aop.framework.ProxyFactoryBean)然后在程序中使用这个代理对象。
还有基于XML配置方式和注解方式。
1.方法前通知,实现接口MethodBeforeAdivce
package proxy; 2 import java.lang.reflect.Method; 4 import org.springframework.aop.MethodBeforeAdvice; 6 public class BeforeLogin implements MethodBeforeAdvice{ 8 public void before(Method method, Object[] args, Object target) throws Throwable { // TODO Auto-generated method stub System.out.println("执行前"); } }
2.被代理对象实现的接口
package proxy; 2 public interface ILogin { public void login(String username,String password); }
3.被代理对象
package proxy; 2 public class Login implements ILogin{ public void login(String username, String password) { // TODO Auto-generated method stub if("tazi".equals(username)&&"123".equals(password)) System.out.println("login success!"); else System.out.println("login fail!"); 10 } }
4.配置文件
<bean id='beforeLogin' class="proxy.BeforeLogin"> </bean> <bean id='login' class="proxy.Login"></bean> <bean id='my_proxy' class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces"> <value>proxy.ILogin</value> </property> <property name="target" ref='login'></property> <property name="interceptorNames"> <list> <value>beforeLogin</value> </list> </property> </bean>
配置文件中<property name="interceptorNames">下的<list>子标签也可以用
<idref local='interceptorLogin2'/>
5.测试
public class Test { public static void main(String[] args) { ApplicationContext apc=new ClassPathXmlApplicationContext("applicationContext.xml"); ILogin login=(ILogin)apc.getBean("my_proxy"); login.login("tazi", "123"); } }
运行结果:
执行前 login success!
另外还有方法后通知,实现AfterReturingAdvice.它仅在方法正常返回后被调用,若方法执行中出现异常则不被调用。它可以看到方法的返回值,却不能改变它,由返回类型是void也可以知道。
void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable
环绕型通知,实现org.aopalliance.intercept.MethodInterceptor(aop联盟定义的,便于在实现规范的aop中迁移)
Object invoke(MethodInvocation invocation) throws Throwable
注意返回值是Object类型,如果希望不影响返回值,应当返回原方法的返回值,即
Object result=invocation.proceed(); //... return result;
invocation参数中封装了原方法的信息,有getMethod(),getArguments()等方法。
异常通知ThrowsAdvice,此接口为标签接口,可以自定义方法名称,只要是如下形式
aferThrowing([Method],[args],[target],Throwable的子类)
二 XML文件的方式
1.引入AOP命名空间
<?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:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd "> <!-- 注解方式必须加上 <aop:aspectj-autoproxy/> --> <!-- 目标对象 --> <bean id="personService" class="com.tazi.service.impl.PersonServiceBean"></bean> <!-- 横切面 --> <bean id="myInterceptor" class="com.tazi.service.MyInterceptor"></bean> <!-- 所有aop配置 --> <aop:config> <!-- 定义一个切面 --> <aop:aspect id="asp" ref="myInterceptor"> <!-- 定义一个切入点,也可以作为<aop:config>的子标签 --> <aop:pointcut id="mycut" expression="execution (* com.tazi.service.impl.PersonServiceBean.*(..))"/> <!-- 前置通知,注意方法没有参数或者有一个JoinPoint类型的参数 --> <aop:before pointcut-ref="mycut" method="doAccess"/> <aop:after pointcut-ref="mycut" method="afterRet"/> 32 </aop:aspect> </aop:config> </beans>
2.建立目标对象,自定义的切面对象(不需要实现任何接口)
package com.tazi.service; 2 3 import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; /* * 切面,交给Spring容器管理 */ 9 public class MyInterceptor { 11 /* * 前置通知 */ public void doAccess(){ System.out.println("前置通知"); } 18 public void afterRet(JoinPoint jPoint){ System.out.println(jPoint.getSignature().getDeclaringTypeName()); System.out.println(jPoint.getSignature().getName()); System.out.println("后置通知"); } public void after(){ System.out.println("最终通知"); } public void expHandle(Exception e) { System.out.println("抛出异常"+e); } 30 public Object huan(ProceedingJoinPoint pjp)throws Throwable{ System.out.println("进入方法"); Object result=pjp.proceed(); System.out.println("退出方法"); return result; 36 } }
3.定义切入点,使用切入点表达式语言
4.配置xml文件
5.测试
三:使用注解的方式
在Spring的配置文件中引入aop命名空间
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation中加入
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
1.打开注解方式的配置项
注解本身不能干活,需要处理器
使用<aop:aspectj-autoproxy/> 提供对注解的解释功能。
2.定义切面、切入点(对业务Bean里面的哪些方法进行拦截),定义通知(拦截到方法以后所要做的工作)。
业务接口和业务方法如下:
package com.tazi.service.impl; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.tazi.service.PersonService; public class PersonServiceBean implements PersonService { public void save(String name) { // TODO Auto-generated method stub System.out.println("save"); throw new RuntimeException("例外"); } public void update() { // TODO Auto-generated method stub } public static void main(String[] args) { ApplicationContext apc=new ClassPathXmlApplicationContext("bean.xml"); PersonService pService=(PersonService)apc.getBean("personService"); pService.save("tazi"); } public String getPersonName(Integer id) { // TODO Auto-generated method stub System.out.println("getName"); return "tazi"; } }
定义切面,使用@Aspect注解,前提是把该切面交给Spring来管理,否则注解没有任何作用。
定义切入点,使用切入点表达式,形如如下形式:
execution表示运行时,后面是[返回值]+空格+包名.类名(包名..类名则表示连同子包)+点号+方法+(..)
注意:方法(..)表示方法的参数任意,*可以表示任意
切入点的名称定义是以一个方法的形式。名称连括号也带上。
定义通知
根据所作的工作是方法的前后位置,有不同的通知。
1 package com.tazi.service; 2 3 import org.aspectj.lang.ProceedingJoinPoint; 4 import org.aspectj.lang.annotation.After; 5 import org.aspectj.lang.annotation.AfterReturning; 6 import org.aspectj.lang.annotation.AfterThrowing; 7 import org.aspectj.lang.annotation.Around; 8 import org.aspectj.lang.annotation.Aspect; 9 import org.aspectj.lang.annotation.Before; 10 import org.aspectj.lang.annotation.Pointcut; 11 /* 12 * 切面,交给Spring容器管理 13 */ 14 @Aspect 15 public class MyInterceptor { 16 /* 17 * 定义一个切入点 18 */ 19 @Pointcut ("execution (* com.tazi.service.impl.PersonServiceBean.*(..))") 20 private void anyMethod(){} 21 22 /* 23 * 前置通知 24 */ 25 @Before("anyMethod() &&args(name)")//多个条件,与参数的名字相同,既然如此,也说明应用的方法必须有一个String类型的参数 26 public void doAccess(String name){ 27 System.out.println("前置通知"+name); 28 } 29 30 @AfterReturning(pointcut="anyMethod()",returning="result")//必须是方法正常执行,若抛出异常则不可能被调用,这里加了返回值,也暗示了所拦截的方法必须带有一个String类型的返回值 31 public void afterRet(String result){ 32 System.out.println("后置通知"+result); 33 } 34 @After("anyMethod()") //无论方法是否抛出异常,都会执行它,相当于在try catch的finally中执行 35 public void after(){ 36 System.out.println("最终通知"); 37 } 38 @AfterThrowing(pointcut="anyMethod()",throwing="e")//当抛出异常时 39 public void expHandle(Exception e) { 40 System.out.println("抛出异常"+e); 41 } 42 43 @Around("anyMethod()") //环绕方法前后,特别适合于权限管理,如果有权限,就调用pjp.proceed()否则不调用,环绕型的通知的方法签名必须是如下形式 44 public Object huan(ProceedingJoinPoint pjp)throws Throwable{ 45 System.out.println("进入方法"); 46 Object result=pjp.proceed(); 47 System.out.println("退出方法"); 48 return result; 49 50 } 51 }
3.最后把切面和业务Bean都在xml配置文件中配置,交给Spring容器管理。
相关文章推荐
- Spring AOP 实现原理与CGLIB应用
- Spring框架学习第四讲(AOP原理——XML实现)
- Spring AOP 实现原理与 CGLIB 应用
- 实现基于Spring框架应用的权限控制系统
- Spring框架与AOP思想的研究与应用
- Spring中应用java动态代码实现Aop
- 实例讲解Java的Spring框架中的AOP实现(精华)
- Spring框架与AOP思想的研究与应用
- 自己实现的一个简易Spring框架(IoC+AOP)
- NFramework开源AOP框架ORM的实现原理与应用-.NET教程,.NET Framework
- 在Delphi中应用AOP实现日志功能
- AOP技术应用和研究--SpringAop实现原理
- AOSD:应用AOP实现业务逻辑
- spring框架学习之路(一)-入门基础(3)-IOC和AOP的综合应用
- NFramework开源AOP框架ORM的实现原理与应用
- Spring AOP 实现原理与 CGLIB 应用
- 在Delphi中应用AOP实现日志功能
- Spring AOP 实现与 CGLIB 应用
- Spring框架与AOP思想的研究与应用
- spring框架—AOP编程的两种实现方式