首页 > 编程语言 > 详细

Java反射—模拟Spring的Aop

时间:2015-07-28 23:11:49      阅读:365      评论:0      收藏:0      [点我收藏+]

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 “,则结果为

  技术分享

  说明返回的是目标对象,而且没有执行增强方法。

版权声明:本文为博主原创文章,未经博主允许不得转载。

Java反射—模拟Spring的Aop

原文:http://blog.csdn.net/wang379275614/article/details/47112195

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!