模拟spring aop (利用java反射原理)

1.    大概流程
  上篇文章已经结合
Java
反射解释了SpringAop的原理,这里我们简单模拟以下
spring
的Aop实现。大体流程如下:
  Ø  创建一个properties配置文件模拟Spring配置文件。
  Ø  创建一个增强接口与一个实现类模拟Spring的Advice。
  Ø  创建一个生成代理的工厂类,并在InvocationHandler类的invoke方法中织入增强方法(即aop)。
  Ø  创建一个生成Bean的工厂类(类似IOC工厂,只创建bean,没有依赖注入的功能),生成Bean时判断,如果是Spring管理的类,则返回目标对象的代理对象,如果不是spring管理的类则直接返回目标对象。
理论不再多说,直接看代码:
2.    实例代码
  2.1   配置文件(config.properties):
[html]
view plain
copy

  1. #1、模拟没有被spring管理的bean的class  
  2. xxx=java.util.ArrayList  
  3. #2、模拟被Spring管理的bean的class  
  4. #xxx=cn.itcast.day3.aopframework.ProxyFactoryBean  
  5.   
  6. #3、xxx的增强类  
  7. xxx.advice=cn.itcast.day3.aopframework.MyAdvice  
  8. #4、xxx的目标类  
  9. xxx.target=java.util.ArrayList  

  2.2  增强接口:
[java]
view plain
copy

  1. package cn.itcast.day3.aopframework;  
  2.   
  3. import java.lang.reflect.Method;  
  4.   
  5. /** 
  6.  * 增强接口 
  7.  *  
  8.  * @author wangzhipeng 
  9.  *  
  10.  */  
  11. public interface Advice {  
  12.     // 前置增强方法  
  13.     void beforeMethod(Method method);  
  14.   
  15.     // 后置增强方法  
  16.     void afterMethod(Method method);  
  17. }  

  2.3  增强实现:
[java]
view plain
copy

  1. package cn.itcast.day3.aopframework;  
  2.   
  3. import java.lang.reflect.Method;  
  4.   
  5. /** 
  6.  * 增强类 
  7.  *  
  8.  * @author wangzhipeng 
  9.  *  
  10.  */  
  11. public class MyAdvice implements Advice {  
  12.     long beginTime = 0;  
  13.   
  14.     /** 
  15.      * 前置增强方法 
  16.      */  
  17.     public void beforeMethod(Method method) {  
  18.         System.out.println(“到TGB来学习啦!”);  
  19.         beginTime = System.currentTimeMillis();  
  20.     }  
  21.   
  22.     /** 
  23.      * 后置增强方法 
  24.      */  
  25.     public void afterMethod(Method method) {  
  26.         System.out.println(“从TGB毕业上班啦!”);  
  27.         long endTime = System.currentTimeMillis();  
  28.         System.out.println(method.getName() + ” running time of ” + (endTime – beginTime));  
  29.   
  30.     }  
  31.   
  32. }  

  2.4  生成代理的工厂类:
[java]
view plain
copy

  1. package cn.itcast.day3.aopframework;  
  2.   
  3. import java.lang.reflect.InvocationHandler;  
  4. import java.lang.reflect.Method;  
  5. import java.lang.reflect.Proxy;  
  6.   
  7. /** 
  8.  * 生成代理的工厂类 
  9.  *  
  10.  * @author wangzhipeng 
  11.  *  
  12.  */  
  13. public class ProxyFactoryBean {  
  14.     // 增强对象  
  15.     private Advice advice;  
  16.     // 目标对象  
  17.     private Object target;  
  18.   
  19.     // 获取目标对象的代理对象  
  20.     public Object getProxy() {  
  21.         Object proxy = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {  
  22.             // InvocationHandler接口的匿名内部类  
  23.             // 执行代理对象的任何方法时都将被替换为执行如下invoke方法  
  24.             public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
  25.   
  26.                 advice.beforeMethod(method);// 执行【前置】增强方法  
  27.                 Object retVal = method.invoke(target, args);// 执行目标方法  
  28.                 advice.afterMethod(method);// 执行【后置】增强方法  
  29.   
  30.                 return retVal;// 返回目标方法执行结果,代理对象的方法返回值必须与目标对象的方法返回值相同  
  31.             }  
  32.         });  
  33.         return proxy;  
  34.     }  
  35.   
  36.     public Advice getAdvice() {  
  37.         return advice;  
  38.     }  
  39.   
  40.     public void setAdvice(Advice advice) {  
  41.         this.advice = advice;  
  42.     }  
  43.   
  44.     public Object getTarget() {  
  45.         return target;  
  46.     }  
  47.   
  48.     public void setTarget(Object target) {  
  49.         this.target = target;  
  50.     }  
  51.   
  52. }  

  2.5  生成Bean的工厂类(类似IOC工厂,这里只能创建bean,没有依赖注入)
[java]
view plain
copy

  1. package cn.itcast.day3.aopframework;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.InputStream;  
  5. import java.util.Properties;  
  6.   
  7. /** 
  8.  * 模拟Spring的IOC工厂(只提供创建bean功能,不能依赖注入) 
  9.  *  
  10.  * @author wangzhipeng 
  11.  *  
  12.  */  
  13. public class BeanFactory {  
  14.     Properties props = new Properties();  
  15.   
  16.     /** 
  17.      * 实例化Bean工厂时会扫描我们的配置文件(传入我们的配置文件) 
  18.      *  
  19.      * @param ips 
  20.      *            配置文件的stream流 
  21.      */  
  22.     public BeanFactory(InputStream ips) {  
  23.         try {  
  24.             props.load(ips);  
  25.         } catch (IOException e) {  
  26.             e.printStackTrace();  
  27.         }  
  28.     }  
  29.   
  30.     /** 
  31.      * 生产bean 
  32.      *  
  33.      * @param name 
  34.      *            bean的名称 
  35.      */  
  36.     public Object getBean(String name) {  
  37.         String className = props.getProperty(name);  
  38.         Object bean = null;  
  39.         try {  
  40.             // 反射获取类名为name的对象  
  41.             Class clazz = Class.forName(className);  
  42.             bean = clazz.newInstance();  
  43.         } catch (Exception e) {  
  44.             e.printStackTrace();  
  45.         }  
  46.         // 如果目标被Spring管理了(这里以如果bean是ProxyFactoryBean类型的对象代替)则返回目标的代理对象,否则直接返回目标对象  
  47.         // 实际的Spring中,可以用spring的配置文件或者注解来判断是否被spring管理  
  48.         if (bean instanceof ProxyFactoryBean) {  
  49.             Object proxy = null;  
  50.             ProxyFactoryBean proxyFactoryBean = (ProxyFactoryBean) bean;  
  51.             try {  
  52.                 // 反射获得增强对象  
  53.                 Advice advice = (Advice) Class.forName(props.getProperty(name + “.advice”)).newInstance();  
  54.                 // 反射获得目标对象  
  55.                 Object target = Class.forName(props.getProperty(name + “.target”)).newInstance();  
  56.                 // 生成目标对象的代理对象,并织入增强方法,实现了aop  
  57.                 proxyFactoryBean.setAdvice(advice);  
  58.                 proxyFactoryBean.setTarget(target);  
  59.                 proxy = proxyFactoryBean.getProxy();  
  60.             } catch (Exception e) {  
  61.                 e.printStackTrace();  
  62.             }  
  63.             return proxy;// 如果目标被spring管理,则返回目标的代理对象  
  64.         }  
  65.         return bean;// 如果没有被spring管理,直接返回目标  
  66.     }  
  67. }  

  2.6  测试类
[java]
view plain
copy

  1. package cn.itcast.day3.aopframework;  
  2.   
  3. import java.io.InputStream;  
  4.   
  5. /** 
  6.  * 测试类 
  7.  *  
  8.  * @author wangzhipeng 
  9.  *  
  10.  */  
  11. public class AopFrameworkTest {  
  12.   
  13.     public static void main(String[] args) throws Exception {  
  14.         // 获得配置文件的stream流  
  15.         InputStream ips = AopFrameworkTest.class.getResourceAsStream(“config.properties”);  
  16.         // 利用bean工厂创建配置文件中配置的类的对象  
  17.         Object bean = new BeanFactory(ips).getBean(“xxx”);  
  18.         // 测试BeanFactory生成的是目标还是代理,如果是代理会执行增强方法  
  19.         System.out.println(bean.getClass().getName());  
  20.         bean.hashCode();  
  21.     }  
    原文作者:AOP
    原文地址: https://blog.csdn.net/qq_34037924/article/details/51375371
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞