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、模拟没有被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 增强接口:
[java]
view plain
copy
- 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 增强实现:
[java]
view plain
copy
- 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 生成代理的工厂类:
[java]
view plain
copy
- 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,没有依赖注入)
[java]
view plain
copy
- 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 测试类
[java]
view plain
copy
- 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();
- }
- }