您的位置:首页 > 编程语言 > Java开发

Java反射—模拟Spring的Aop

2015-07-28 21:52 489 查看

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


  说明返回的是目标对象,而且没有执行增强方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: