1. 大概流程
上篇文章已经结合Java反射解释了SpringAop的原理,这里我们简单模拟以下Spring的Aop实现。大体流程如下:
? 创建一个properties配置文件模拟Spring配置文件。
? 创建一个增强接口与一个实现类模拟Spring的Advice。
? 创建一个生成代理的工厂类,并在InvocationHandler类的invoke方法中织入增强方法(即aop)。
? 创建一个生成Bean的工厂类(类似IOC工厂,只创建bean,没有依赖注入的功能),生成Bean时判断,如果是Spring管理的类,则返回目标对象的代理对象,如果不是spring管理的类则直接返回目标对象。理论不再多说,直接看代码:
2. 实例代码
2.1 配置文件(config.properties):
#1、模拟没有被spring管理的bean的class xxx=java.util.ArrayList #2、模拟被Spring管理的bean的class #xxx=cn.itcast.day3.aopframework.ProxyFactoryBean #3、xxx的增强类 xxx.advice=cn.itcast.day3.aopframework.MyAdvice #4、xxx的目标类 xxx.target=java.util.ArrayList
2.2 增强接口:
package cn.itcast.day3.aopframework; import java.lang.reflect.Method; /** * 增强接口 * * @author wangzhipeng * */ public interface Advice { // 前置增强方法 void beforeMethod(Method method); // 后置增强方法 void afterMethod(Method method); }
2.3 增强实现:
package cn.itcast.day3.aopframework; import java.lang.reflect.Method; /** * 增强类 * * @author wangzhipeng * */ public class MyAdvice implements Advice { long beginTime = 0; /** * 前置增强方法 */ public void beforeMethod(Method method) { System.out.println("到TGB来学习啦!"); beginTime = System.currentTimeMillis(); } /** * 后置增强方法 */ public void afterMethod(Method method) { System.out.println("从TGB毕业上班啦!"); long endTime = System.currentTimeMillis(); System.out.println(method.getName() + " running time of " + (endTime - beginTime)); } }
2.4 生成代理的工厂类:
package cn.itcast.day3.aopframework; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * 生成代理的工厂类 * * @author wangzhipeng * */ public class ProxyFactoryBean { // 增强对象 private Advice advice; // 目标对象 private Object target; // 获取目标对象的代理对象 public Object getProxy() { Object proxy = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { // InvocationHandler接口的匿名内部类 // 执行代理对象的任何方法时都将被替换为执行如下invoke方法 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { advice.beforeMethod(method);// 执行【前置】增强方法 Object retVal = method.invoke(target, args);// 执行目标方法 advice.afterMethod(method);// 执行【后置】增强方法 return retVal;// 返回目标方法执行结果,代理对象的方法返回值必须与目标对象的方法返回值相同 } }); return proxy; } public Advice getAdvice() { return advice; } public void setAdvice(Advice advice) { this.advice = advice; } public Object getTarget() { return target; } public void setTarget(Object target) { this.target = target; } }
2.5 生成Bean的工厂类(类似IOC工厂,这里只能创建bean,没有依赖注入)
package cn.itcast.day3.aopframework; import java.io.IOException; import java.io.InputStream; import java.util.Properties; /** * 模拟Spring的IOC工厂(只提供创建bean功能,不能依赖注入) * * @author wangzhipeng * */ public class BeanFactory { Properties props = new Properties(); /** * 实例化Bean工厂时会扫描我们的配置文件(传入我们的配置文件) * * @param ips * 配置文件的stream流 */ public BeanFactory(InputStream ips) { try { props.load(ips); } catch (IOException e) { e.printStackTrace(); } } /** * 生产bean * * @param name * bean的名称 */ public Object getBean(String name) { String className = props.getProperty(name); Object bean = null; try { // 反射获取类名为name的对象 Class clazz = Class.forName(className); bean = clazz.newInstance(); } catch (Exception e) { e.printStackTrace(); } // 如果目标被Spring管理了(这里以如果bean是ProxyFactoryBean类型的对象代替)则返回目标的代理对象,否则直接返回目标对象 // 实际的Spring中,可以用spring的配置文件或者注解来判断是否被spring管理 if (bean instanceof ProxyFactoryBean) { Object proxy = null; ProxyFactoryBean proxyFactoryBean = (ProxyFactoryBean) bean; try { // 反射获得增强对象 Advice advice = (Advice) Class.forName(props.getProperty(name + ".advice")).newInstance(); // 反射获得目标对象 Object target = Class.forName(props.getProperty(name + ".target")).newInstance(); // 生成目标对象的代理对象,并织入增强方法,实现了aop proxyFactoryBean.setAdvice(advice); proxyFactoryBean.setTarget(target); proxy = proxyFactoryBean.getProxy(); } catch (Exception e) { e.printStackTrace(); } return proxy;// 如果目标被spring管理,则返回目标的代理对象 } return bean;// 如果没有被spring管理,直接返回目标 } }
2.6 测试类
package cn.itcast.day3.aopframework; import java.io.InputStream; /** * 测试类 * * @author wangzhipeng * */ public class AopFrameworkTest { public static void main(String[] args) throws Exception { // 获得配置文件的stream流 InputStream ips = AopFrameworkTest.class.getResourceAsStream("config.properties"); // 利用bean工厂创建配置文件中配置的类的对象 Object bean = new BeanFactory(ips).getBean("xxx"); // 测试BeanFactory生成的是目标还是代理,如果是代理会执行增强方法 System.out.println(bean.getClass().getName()); bean.hashCode(); } }
2.7 测试结果1:
如果配置文件中配置的是“xxx=cn.itcast.day3.aopframework.ProxyFactoryBean “,则结果为
说明返回的是代理对象,而且执行了增强方法。(因为我们的BeanFactory中有相关的判断【if(bean instanceof ProxyFactoryBean)】)。
2.8 测试结果2
如果配置文件中配置的是“xxx=cn.itcast.day3.aopframework.ProxyFactoryBean “,则结果为
说明返回的是目标对象,而且没有执行增强方法。
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-27 13:53:38