AOP简易例子-重在理解作用

来源:互联网 发布:2016it行业发展前景 编辑:程序博客网 时间:2024/04/28 16:08
最近在研究aop,看了点资料,总结如下: 
所谓AOP就是将分散在各个方法处的公共代码提取到一处,并通过类似拦截器的机制实现代码的动态整合。可以简单地想象成,在某个方法的调用前、执行中、调用后和抛出异常时,动态插入自己的代码。 

网上碰到个例子还不错,整理了一下: 

首先看一个简单的spring IOC例子: 

用户买书接口: 
Java代码  收藏代码
  1. package aop;  
  2. public interface BuyBook {    
  3.     public void buyBook(String customer,String book)throws NoBookException;  
  4. }  


用户买书的接口实现: 
Java代码  收藏代码
  1. package aop;  
  2. public class BuyBookImpl implements BuyBook{  
  3.     public void buyBook(String customer,String book) {        
  4.         System.out.println(customer+"你好!你成功购了一本"+book+"!");  
  5.     }  
  6. }  


测试用户买书类: 
Java代码  收藏代码
  1. package aop;  
  2. import org.springframework.context.ApplicationContext;  
  3. import org.springframework.context.support.FileSystemXmlApplicationContext;  
  4.   
  5. public class TestAop {  
  6.     public static void main(String args[]) throws Exception{          
  7.         ApplicationContext ctx = new FileSystemXmlApplicationContext("aop.xml");     
  8.         BuyBook b = (BuyBook)ctx.getBean("newBuyBook");  
  9.         b.buyBook("小东""《楚留香》");  
  10.     }  
  11. }  


配置文件aop.xml 
Xml代码  收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">  
  3. <beans>  
  4.     <bean id="newBuyBook" class="aop.BuyBookImpl"/>   
  5. </beans>  


此时运行程序仅出现: 
小东你好!你成功购了一本《楚留香》! 

=================================================================================== 
AOP ----切面编程 
所谓切面编程:在不改变原方法(令为methodA)的定义与使用、也不改变原程序的流程的情况下,变更该methodA的功能。在变更时,最激动人心的时能获得methodA的类的对象,meahtoidA的参数,也可获得mehodA执行的结果,还能得到调用meahtoidA的对象。 
    简单理解:允许用户在指定地方,插入新的函数, 
包括: 
1 methodA运行前,执行用户指定的其它方法methodOther,然后返回 
2 methodA运行完毕,执行用户指的其它方法methodOther,然后返回 
3 在执行methodA的地方,变成执行在用户指定的其它方法methodOther, 
在methodOther方法中, methodA运不运行,何时运行,随用户自行安排,然后返回 
4  methodA执行出现异常时,执行用户指定的其它方法methodOther,然后返回。 

产生动机: 
在一个程序中,当我们要 使用一个方法(令为methodA);由于不同的用户对methodA的功能要 求不一样,因此在这个methodA的地方就出现了变化点。所以要在这个变化点上进行封装,留下一个可扩展的接口,便于日后修改维护。 

本质: 
1  Aop核心是一个适配器,把变动前的方法,与变动后的方法联接在一起。 
2  这个适配器实现的核心是动态代理 Proxy机制 
3  四个核心子接口: 
a  MethodBeforeAdvice ----methodA函数调用前执行用户定义的方法 
b  AfterReturningAdvice ----- methodA函数调后执行用户定义的方法 
c  MethodInterceptor -------彻底变更MethodA函数为用户定义的方法 
d  ThrowsAdvice------methodA函数调用出现异常执行用户定义的方法
 

=================================================================================== 
下面加入aop的内容: 
一、在买书前加入新功能(欢迎光临!小东) 

增加类MyBeforeAdvice : 
Java代码  收藏代码
  1. package aop;  
  2. import org.springframework.aop.MethodBeforeAdvice;  
  3. import java.lang.reflect.Method;  
  4.   
  5. public class MyBeforeAdvice implements MethodBeforeAdvice{  
  6.     public void before(Method arg0, Object[] arg1, Object target) throws Throwable {  
  7.     String customer = (String)arg1[0];        
  8.         System.out.println("欢迎光临!"+customer+"!");     
  9.     }     
  10. }  


修改配置文件aop.xml: 
Xml代码  收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">  
  3. <beans>  
  4.     <bean id="buyBook" class="aop.BuyBookImpl"/>   
  5.     <bean id="myBeforeAdvice" class="aop.MyBeforeAdvice"/>  
  6.     <bean id="newBuyBook" class="org.springframework.aop.framework.ProxyFactoryBean">  
  7.         <property name="proxyInterfaces" value="aop.BuyBook"/>   
  8.         <property name="interceptorNames">  
  9.             <list>  
  10.                   <value>myBeforeAdvice</value>  
  11.             </list>  
  12.         </property>  
  13.         <property name="target" ref="buyBook"/>  
  14.     </bean>  
  15. </beans>  


运行后输出结果: 
欢迎光临! 
小东你好!你成功购了一本《楚留香》! 


二、在买书后加入新功能(Good Bye!小东)
 
增加MyAfterAdvice类: 
Java代码  收藏代码
  1. package aop;  
  2. import java.lang.reflect.Method;  
  3. import org.springframework.aop.AfterReturningAdvice;  
  4. public class MyAfterAdvice implements AfterReturningAdvice{   
  5.     public void afterReturning(Object o1, Method m, Object[] objects, Object o2){     
  6.         System.out.println("Good Bye!" + objects[0]);         
  7.     }  
  8. }  


修改配置文件aop.xml: 
Xml代码  收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">  
  3. <beans>  
  4.     <bean id="buyBook" class="aop.BuyBookImpl"/>   
  5.     <bean id="myBeforeAdvice" class="aop.MyBeforeAdvice"/>  
  6.     <bean id="myAfterAdvice" class="aop.MyAfterAdvice"/>  
  7.     <bean id="newBuyBook" class="org.springframework.aop.framework.ProxyFactoryBean">  
  8.         <property name="proxyInterfaces" value="aop.BuyBook"/>   
  9.         <property name="interceptorNames">  
  10.             <list>  
  11.                   <value>myBeforeAdvice</value>  
  12.                   <value>myAfterAdvice</value>  
  13.             </list>  
  14.         </property>  
  15.         <property name="target" ref="buyBook"/>  
  16.     </bean>  
  17. </beans>  



运行后输出结果: 
欢迎光临! 
小东你好!你成功购了一本《楚留香》! 
Good Bye!小东 

三、修改原来方法的内容,比如加入相关业务判断,一个人只能买一本书: 
修改用户买书类: 
Java代码  收藏代码
  1. package aop;  
  2. import org.springframework.context.ApplicationContext;  
  3. import org.springframework.context.support.FileSystemXmlApplicationContext;  
  4.   
  5. public class TestAop {  
  6.     public static void main(String args[]) throws Exception{          
  7.         ApplicationContext ctx = new FileSystemXmlApplicationContext("aop.xml");     
  8.         BuyBook b = (BuyBook)ctx.getBean("newBuyBook");  
  9.         b.buyBook("小东""《楚留香》");  
  10.         b.buyBook("小东""《楚留香2》");  
  11.     }  
  12. }  


增加拦截器类MyMethodInterceptor: 
Java代码  收藏代码
  1. package aop;  
  2. import java.util.HashSet;  
  3. import java.util.Set;  
  4. import org.aopalliance.intercept.MethodInterceptor;  
  5. import org.aopalliance.intercept.MethodInvocation;  
  6. public class MyMethodInterceptor implements MethodInterceptor{  
  7.     private Set customers = new HashSet();    
  8.     @Override  
  9.     public Object invoke(MethodInvocation invocation) throws Throwable {  
  10.         String customer = (String)invocation.getArguments()[0];  
  11.         Object result = null;  
  12.         if(customers.contains(customer)){  
  13.              System.out.println("注意,一名顾客只能买一本打折书!");  
  14.         } else{  
  15.              result = invocation.proceed();  
  16.         }  
  17.         customers.add(customer);  
  18.         return result;  
  19.     }  
  20. }  



修改配置文件aop.xml: 
Xml代码  收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">  
  3. <beans>  
  4.     <bean id="buyBook" class="aop.BuyBookImpl"/>   
  5.     <bean id="myMethodInterceptor" class="aop.MyMethodInterceptor"/>  
  6.   
  7.     <bean id="newBuyBook" class="org.springframework.aop.framework.ProxyFactoryBean">  
  8.         <property name="proxyInterfaces" value="aop.BuyBook"/>   
  9.         <property name="interceptorNames">  
  10.             <list>  
  11.                   <value>myMethodInterceptor</value>  
  12.             </list>  
  13.         </property>  
  14.         <property name="target" ref="buyBook"/>  
  15.     </bean>  
  16. </beans>  


运行结果: 
小东你好!你成功购了一本《楚留香》! 
注意,一名顾客只能买一本打折书! 
0 0