通过实例理解Spring的Bean工厂和AOP框架

一、需求设想      

       现在我有一个配置文件,里面配置了Bean的相关信息,如bean的类名(包括包名)、代理工厂(主要负责产生代理类)、目标类(被代理的类)、业务织入接口(Advice)。然后通过BeanFactory来产生Bean的实例,如果配置文件中配置的Bean是ProxyFactoryBean的实例,我们则产生这个Bean一个代理类的实例,还可以通过此配置文件进行切换,是使用代理类还是使用目标类来完成相应的业务功能,该配置文件的格式如下:


                                                                                                                    图1-1

图1-1中所示,beanName就是我们要通过Bean工厂动态产生的实例或代理类实例,如果配置文件中的beanName指定的是ProxyFactoryBean,则获得的实例则是根据beanName.target对应的类名,由ProxyFactoryBean产生一个代理类的实例,并由beanName.advice对应的Advice织入相应的业务功能到该目标类中。

二、功能实现

1、步聚:
       BeanFactory即然是专门用来产生Bean的,那就必须得知道产生这些个Bean的配置文件在哪里?这个配置文件事是先由程序员配置好的。所以在初始化BeanFactory的时候,就必要要得到产生这些Bean的配置文件。
            1)、创建BeanFactory的一个唯一的构造方法,接收一个InputStream参数,这个参数用于获得Bean的配置文件。初始化的时候,通过Properties对象加载这个配置文件。
            2)、创建一个getBean方法,接收一个参数(类名),用于根据beanName动态创建该类的一个实例。该beanName就是配置文件中的beanName。
            3)、使用Class.forName方法根据beanName产生一个Class字节码对象,并产生一个实例对象
            4)、如果该实例对象是ProxyFactoryBean的实例,则返回由ProxyFactoryBean产生的一个代理类实例,并注入配置文件中beanName.advice对应的Advice,否则直接返回该实例。

2、代码实例
1)、BeanFactory类
package proxy.aopframework;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import proxy.Advice;

/**
 * Bean工厂,负责产生代理类或目标类的实例
 */
public class BeanFactory<T> {
	
	private Properties props = new Properties();
	
	/**
	 * 初始化bean工厂,加载bean的配置文件,该配置文件是一个标准的Properties文件,该文件由Key=Value的格式组成
	 * @param inStream bean的配置文件
	 */
	public BeanFactory(InputStream inStream) {
		try {
			props.load(inStream);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 获取一个Bean的实例
	 * @param beanName bean javabean的名称
	 * @return 根据配置文件,返回目标类或代理类的实例
	 * @throws ClassNotFoundException
	 */
	public T getBean(String beanName) throws ClassNotFoundException {
		String className = props.getProperty(beanName);
		Class clazz = Class.forName(className);
		T bean = null;
		try {
			bean = (T)clazz.newInstance();
			if (bean instanceof ProxyFactoryBean) {
				ProxyFactoryBean proxyFactoryBean = (ProxyFactoryBean) bean;
				Advice advice = (Advice) Class.forName(props.getProperty(beanName + ".advice")).newInstance();
				Object target = Class.forName(props.getProperty(beanName + ".target")).newInstance();
				proxyFactoryBean.setAdvice(advice);
				proxyFactoryBean.setTarget(target);
				bean = (T)proxyFactoryBean.getProxy();
			}
		} catch (Exception e) {
			e.printStackTrace();
		} 
		return bean;
	}
}
2)、ProxyFactoryBean类
package proxy.aopframework;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import proxy.Advice;

/**
 * 代理工厂,负责产生目标对象的代理类
 */
public class ProxyFactoryBean {
	
	/**
	 * 被代理的目标对象
	 */
	private Object target;
	
	/**
	 * 目标对象要插入的业务逻辑
	 */
	private Advice advice;

	public Object getTarget() {
		return target;
	}

	public void setTarget(Object target) {
		this.target = target;
	}

	public Advice getAdvice() {
		return advice;
	}

	public void setAdvice(Advice advice) {
		this.advice = advice;
	}

	/**
	 * 获得一个代理类对象
	 * @return
	 */
	public Object getProxy() {
		return Proxy.newProxyInstance(
				target.getClass().getClassLoader(), 
				target.getClass().getInterfaces(),
				new InvocationHandler() {
					@Override
					public Object invoke(Object proxy, Method method,
							Object[] args) throws Throwable {
						Object retVal = null;
						try {
							advice.doBefore(target, method, args);
							retVal = method.invoke(target, args);
							advice.doAfter(target, method, args, retVal);
						} catch (Exception e) {
							advice.doThrow(target, method, args, e);
						} finally {
							advice.doFinally(target, method, args);
						}
						return retVal;
					}}
				);
	}
}
3)、Advice接口和LogAdvice实现类
package proxy;

import java.lang.reflect.Method;

/**
 * aop接口,提供方法运行前、方法运行后、方法运行中产生Exception、方法最终运行代码
 *
 */
public interface Advice {
	
	/**
	 * 方法运行前
	 * @param target 被代理的目标对象
	 * @param method 被调用的方法
	 * @param args 方法的参数
	 */
	public void doBefore(Object target, Method method, Object[] args);
	
	/**
	 * 方法运行后
	 * @param target 被代理的目标对象
	 * @param method 被调用的方法对象
	 * @param args 方法的参数
	 * @param retVal 方法的返回值
	 */
	public void doAfter(Object target, Method method, Object[] args, Object retVal);
	
	/**
	 * 方法运行时产生的异常
	 * @param target 被代理的目标对象
	 * @param method 被调用的方法
	 * @param args 方法参数
	 * @param e 运行时的异常对象
	 */
	public void doThrow(Object target, Method method, Object[] args, Exception e);
	
	/**
	 * 最终要执行的功能(如释放数据库连接的资源、关闭IO流等)
	 * @param target 被代理的目标对象
	 * @param method 被调用的方法
	 * @param args 方法参数
	 */
	public void doFinally(Object target, Method method, Object[] args);
}



package proxy;

import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * 日志功能切入类
 * @author 杨信
 *
 */
public class LogAdvice implements Advice {

	long beginTime = System.currentTimeMillis();
	
	@Override
	public void doBefore(Object target, Method method, Object[] args) {
		System.out.println(target.getClass().getSimpleName() +
				"." + method.getName() + "方法被调用,参数值:" + Arrays.toString(args));

	}
	
	@Override
	public void doAfter(Object target, Method method, Object[] args, Object retVal) {
		long endTime = System.currentTimeMillis();
		System.out.println(target.getClass().getSimpleName() +
				"." + method.getName() + "方法运行结束,返回值:" + retVal + ",耗时" + (endTime - beginTime) + "毫秒。");

	}

	@Override
	public void doThrow(Object target, Method method, Object[] args,
			Exception e) {
		System.out.println("调用" + target.getClass().getSimpleName() +
				"." + method.getName() + "方法发生异常,异常消息:");
		e.printStackTrace();
	}

	@Override
	public void doFinally(Object target, Method method, Object[] args) {
		System.out.println("doFinally...");
		
	}

}
4)、config.properties文件
#beanName=java.util.ArrayList
beanName=proxy.aopframework.ProxyFactoryBean
beanName.advice=proxy.LogAdvice
beanName.target=java.util.ArrayList

#hashMap=java.util.HashMap
hashMap=proxy.aopframework.ProxyFactoryBean
hashMap.advice=proxy.LogAdvice
hashMap.target=java.util.HashMap
5)、测试类AopFrameworkTest
package proxy.aopframework;

import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

public class AopFrameworkTest {

	public static void main(String[] args) throws ClassNotFoundException {
		InputStream inStream = AopFrameworkTest.class.getResourceAsStream("config.properties");
		/*BeanFactory<ArrayList> beanFactory = new BeanFactory<ArrayList>(inStream);
		List list = beanFactory.getBean("ArrayList");
		System.out.println(list.getClass().getName());
		list.add("zhangsan");*/
		
		BeanFactory<HashMap> beanFactory = new BeanFactory<HashMap>(inStream);
		Map map = beanFactory.getBean("hashMap");
		System.out.println(map.getClass().getName());
		map.put("name", "zhangsan");
		System.out.println(map.size());
	}

}
6)、测试结果

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xyang0917

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值