实现相仿Spring的可配置的AOP框架

实现类似Spring的可配置的AOP框架

可配置的AOP框架中两个重要的类:

BeanFactory

工厂类BeanFactory负责创建目标或代理类的实例对象,并通过配置文件进行切换,其getBean()方法根据参数字符串返回一个相应的实例对象,如果参数字符串在配置文件中对应的类名不是ProxyFactoryBean(根据本例子),则直接返回该类的实例对象,否则返回该类实例对象的getProxy()方法返回的对象。

BeanFactory的构造方法接收代表配置文件的输入流对象,配置文件格式:

#xxx=java.util.ArrayList        不是ProxyFactoryBean类

xxx=cn.test.ProxyFactoryBean

xxx.target=java.util.ArrayList        #目标类。

xxx.advice=cn.test.Myadvice       #系统方法类。对目标类添加自定义的方法

 

ProxyFactoryBean

充当封装生成动态代理的工厂,需要为工厂提供:

1.目标对象(target)

2.系统方法类对象(Advice)

 

编写客户端应用

1.编写实现Advice接口的类和在配置文件中进行配置

2.调用BeanFactory获取对象

 

代码实现

1.编写Advice接口类

/*
 * 系统功能的接口类
 */
public interface Advice {
	void beforMethod(); // 在目标方法之前的系统功能方法(只传递目标方法method,可传递目标对象target,method,参数args)

	void afterMethod(Method method); // 在目标方法之后的系统功能方法
}


 

2.实现Advice接口

/*
 * 实现系统功能接口的类
 */
public class MyAdvice implements Advice {
	private long startTime = 0;

	@Override
	public void beforMethod() {
		System.out.println("----调用目标方法之前的系统方法");
		startTime = System.currentTimeMillis();
	}

	@Override
	public void afterMethod(Method method) {
		System.out.println("----调用目标方法之后的系统方法");
		long endTime = System.currentTimeMillis();
		System.out
				.println(method.getName() + "  执行时间:" + (endTime - startTime));
	}

}


 

3.编写配置文件config.properties

#xxx=java.util.ArrayList
xxx=com.test.aopframework.ProxyFactoryBean
#实现Advice接口的类
xxx.advice=com.test.proxy.MyAdvice
#配置需要代理的目标类             
xxx.target=java.util.ArrayList

 

4.BeanFactory类(创建目标类或代理类的实例对象)

/*
 * JavaBean类
 */
public class BeanFactory {
	Properties props = new Properties(); // 配置.property文件,通过property取出值

	public BeanFactory(InputStream ips) {
		try {
			props.load(ips);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public Object getBean(String name) {
		String propertyName = props.getProperty(name); // 取出配置文件属性值
		Object bean = null;
		try {
			Class clazz = Class.forName(propertyName); // 得到属性值的字节码
			bean = clazz.newInstance();
		} catch (Exception e) {
			e.printStackTrace();
		} // 得到实例对象
		if (bean instanceof ProxyFactoryBean) {
			Object proxy=null;
			try {
				ProxyFactoryBean proxyFactoryBean = (ProxyFactoryBean) bean;
				Advice advice=(Advice) Class.forName((String) props.getProperty(name+".advice")).newInstance();
				Object target=Class.forName(props.getProperty(name+".target")).newInstance();
				proxyFactoryBean.setAdvice(advice); // 设置代理对象类的系统方法类对象
				proxyFactoryBean.setTarget(target); // 设置代理对象类的目标类对象
				proxy= proxyFactoryBean.getProxy(); // 得到代理对象
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return proxy;
		}

		return bean;
	}
}


 

5.ProxyFactoryBean(充当封装生成动态代理的工厂)

/*
 * 充当封装生成动态代理的工厂
 */
public class ProxyFactoryBean {
	private Advice advice; // 定义系统方法类对象
	private Object target; // 定义目标对象

	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;
	}

	public Object getProxy() { // 创建代理方法
		return (Object) Proxy.newProxyInstance(
			    target.getClass().getClassLoader(), // 实现的是和目标对象相同的类加载器
				target.getClass().getInterfaces(), // 实现的是和目标对象相同的接口
				new InvocationHandler() {

					@Override
					// proxy:代表代理的对象 method:代表代理对象调用的方法 args:代表调用方法接收的参数
					public Object invoke(Object proxy, Method method,
							Object[] args) throws Throwable {
						advice.beforMethod();
						Object retVal = method.invoke(target, args); // 反射机制,调用目标对象target的方法
						advice.afterMethod(method); // ////传递给目标target
						// return对象将返回给代理。可将值进行过滤
						return retVal;
					}
				});
	}

}


6.编写客户端应用

/*
 * 编写客户端应用aop框架
 */
public class ClientAopFrameWork {
	public static void main(String[] args) {
		InputStream ips = ClientAopFrameWork.class
				.getResourceAsStream("config.properties");
		Object bean = new BeanFactory(ips).getBean("xxx");
		System.out.println(bean);
	}
}