Autumn,仿Spring IOC/AOP集成开发框架

为了能更为深入理解Spring原理,知道怎么用还不如会自己做,于是便动手完成了这个集成框架。功能点仿照Spring,包括IOC中的注入、延迟加载、装配集合等等一系列功能,AOP是采用jdk动态代理实现的,没用CGLIB,因此,被代理的对象必须继承某个接口。

源代码主要为:

ConfigManager.java    负责解析xml、装配bean、获取bean等操作,是框架最重要的类。

ParserHelper.java    辅助XML解析的类。

ProxyHandler.java    代理类,用于支持AOP功能。

ProceedingJoinPoint.java    为了能够实现代理链,封装了Method、Object、args对象以及execute()方法。

AspectInfo.java    切面信息对象。

autumn.dtd    DTD文件,用于约束配置文件语法。

 

源码如下:

ConfigManager.java

package cn.seu.bingluo.ioc;

import java.lang.reflect.InvocationTargetException;

/*
 * By Bingluo 2012.8.17
 * cose.seu.edu.cn
 */

public class ConfigManager {
	// 存放dom
	private Document dom;
	private Element root;
	// 从配置中生成的bean放入map中
	private HashMap<String, Object> beans = new HashMap<String, Object>();

	// 在构造函数时,初始化dom树
	public ConfigManager(String xmlUrl) {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		factory.setIgnoringElementContentWhitespace(true);
		DocumentBuilder db;
		try {
			db = factory.newDocumentBuilder();
			dom = db.parse(xmlUrl);
			dom.normalize();
			root = dom.getDocumentElement();
			System.out.println("IOC/AOP初始化开始...");
			initBeans();
			System.out.println("IOC/AOP初始化结束...");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	// 初始化配置文件中所有非懒加载的bean
	private void initBeans() {
		for (Node node = root.getFirstChild(); node != null; node = node
				.getNextSibling()) {
			// 延迟加载Bean
			if (node.getNodeName().equals("bean")
					&& ((Element) node).hasAttribute("lazy-init")
					&& ((Element) node).getAttribute("lazy-init")
							.equals("true"))
				continue;
			else if (node.getNodeType() == Node.ELEMENT_NODE
					&& node.getNodeName().equals("bean"))
				// 普通bean
				// 创建后,存入map中
				beans.put(((Element) node).getAttribute("id"), initBean(node));
			else if (node.getNodeType() == Node.ELEMENT_NODE
					&& node.getNodeName().equals("aop-config")) {
				// aop配置
				initAOP(node);
			}
		}
	}

	//AOP配置
	private void initAOP(Node aopConfig) {
		for (Node node = aopConfig.getFirstChild(); node != null; node = node
				.getNextSibling()) {
			// 为切面节点,配置增强
			if (node.getNodeType() == Node.ELEMENT_NODE
					&& node.getNodeName().equals("aspect")) {
				initAspect(node);
			}
		}
	}

	//配置AOP切面
	private void initAspect(Node aspect) {
		String aspectRef = ((Element) aspect).getAttribute("ref");
		Object adviceBean = null;
		String expression = "";
		Method beforeMethod = null;
		Method aroundMethod = null;
		Method afterMethod = null;
		if (beans.containsKey(aspectRef)) {
			// 在beans的map中发现已初始化过该bean
			adviceBean = beans.get(aspectRef);
		} else {
			// 未初始化过该bean
			Node e = dom.getElementById(aspectRef);
			if (e.getNodeName().equals("bean")) {
				// 递归调用,初始化被引用的bean
				adviceBean = initBean(e);
			}
		}

		// 获取切点
		// ***************1个切面默认最多只有1个切点、1个前置增强、1个后置增强、1个环绕增强
		Node pointcutNode = ParserHelper.getNode(aspect, "pointcut");
		expression = ((Element) pointcutNode).getAttribute("expression");

		// 获取该切面的增强
		for (Node currentNode = aspect.getFirstChild(); currentNode != null; currentNode = currentNode
				.getNextSibling()) {
			if (currentNode.getNodeType() != Node.ELEMENT_NODE)
				continue;

			// 为相应的增强赋值
			String methodName = ((Element) currentNode).getAttribute("method");
			try {
				if (currentNode.getNodeName().equals("before")) {
					beforeMethod = adviceBean.getClass().getMethod(methodName);
				} else if (currentNode.getNodeName().equals("around")) {
					aroundMethod = adviceBean.getClass().getMethod(methodName,
							ProceedingJoinPoint.class);
				} else if (currentNode.getNodeName().equals("after")) {
					afterMethod = adviceBean.getClass().getMethod(methodName);
				}
			} catch (SecurityException e) {
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				e.printStackTrace();
			}
		}

		// 将该切面交给代理维护
		AspectInfo aspectInfo = new AspectInfo(expression, adviceBean,
				beforeMethod, aroundMethod, afterMethod);
		ProxyHandler.addAspectInfo(aspectInfo);
	}

	//初始化Bean
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private Object initBean(Node node) {
		// 初始化的类型
		Class c = null;
		// 需要初始化的bean
		Object object = null;
		// 生成对象
		try {
			c = Class.forName(((Element) node).getAttribute("class"));
			object = c.newInstance();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}

		// 如果此bean为基本类型bean
		if (isPrimitive(((Element) node).getAttribute("class"))
				|| ((Element) node).hasAttribute("value")) {
			object = getInstanceForName(((Element) node).getAttribute("class"),
					((Element) node).getAttribute("value"));
			return object;
		}

		boolean constructorInit = false;// 是否为构造函数注入
		ArrayList<Class> parameterTypes = new ArrayList<Class>();
		ArrayList<Object> parameters = new ArrayList<Object>();
		// 为bean配置属性
		for (Node property = node.getFirstChild(); property != null; property = property
				.getNextSibling()) {
			if (property.getNodeType() != Node.ELEMENT_NODE) {
				continue;
			}

			if (property.getNodeName().equals("constructor-arg")) {
				// bean为构造函数注入
				constructorInit = true;
				if (((Element) property).hasAttribute("value")) {
					// 该参数为基本类型参数
					getInstanceForName(
							((Element) property).getAttribute("type"),
							((Element) property).getAttribute("value"));
					Class temp = nameToPrimitiveClass(((Element) property)
							.getAttribute("type"));
					parameterTypes.add(temp);
					parameters.add(getInstanceForName(
							((Element) property).getAttribute("type"),
							((Element) property).getAttribute("value")));
				} else if (((Element) property).hasAttribute("ref")) {
					String refId = ((Element) property).getAttribute("ref");
					// 该参数为外部bean引用属性
					if (beans.containsKey(refId)) {
						// 在beans的map中发现已初始化过该bean
						parameterTypes.add(beans.get(refId).getClass());
						parameters.add(beans.get(refId));
					} else {
						// 未初始化过该bean
						Node e = dom.getElementById(refId);
						if (e.getNodeName().equals("bean")) {
							// 递归调用,初始化被引用的bean
							Class temp = null;
							try {
								temp = Class.forName(((Element) e)
										.getAttribute("class"));
							} catch (ClassNotFoundException e1) {
								e1.printStackTrace();
							}
							parameterTypes.add(temp);
							parameters.add(initBean(e));
						}
					}
				}
			} else if (property.getNodeName().equals("property")) {
				// bean为普通属性注入
				String propertyName = ((Element) property).getAttribute("name");
				// 获取该属性对应的set方法
				Method[] methods = c.getMethods();
				Method method = null;
				for (int k = 0; k < methods.length; k++) {
					if (methods[k].getName().equalsIgnoreCase(
							"set" + propertyName)) {
						method = methods[k];
					}
				}

				Object value = null;// 属性值

				if (((Element) property).hasAttribute("value")) {
					// 该属性为直接属性,非外部bean引用属性
					String propertyValue = ((Element) property)
							.getAttribute("value");
					Class<?>[] types = method.getParameterTypes();
					value = getInstanceForName(types[0].getName(),
							propertyValue);

				} else if (((Element) property).hasAttribute("ref")) {
					String refId = ((Element) property).getAttribute("ref");
					// 该属性为外部bean引用属性
					if (beans.containsKey(refId)) {
						// 在beans的map中发现已初始化过该bean
						value = beans.get(refId);
					} else {
						// 未初始化过该bean
						Node e = dom.getElementById(refId);
						if (e.getNodeName().equals("bean")) {
							// 递归调用,初始化被引用的bean
							value = initBean(e);
						}
					}
				} else if (ParserHelper.containNode(property, "bean")) {
					// 该属性为内部bean引用属性
					Node innerBeanNode = null;
					for (innerBeanNode = property.getFirstChild(); innerBeanNode != null; innerBeanNode = innerBeanNode
							.getNextSibling()) {
						if (innerBeanNode.getNodeName().equals("bean")) {
							break;
						}
					}
					value = initBean(innerBeanNode);
				} else if (ParserHelper.containNode(property, "list")
						|| ParserHelper.containNode(property, "set")) {
					// 属性为list、set集合类型
					Collection<Object> collection = ParserHelper.containNode(
							property, "list") ? new ArrayList<Object>()
							: new HashSet();
					for (Node currentNode = property.getFirstChild()
							.getFirstChild(); currentNode != null; currentNode = currentNode
							.getNextSibling()) {
						if (currentNode.getNodeName().equals("ref")
								&& (((Element) currentNode)
										.hasAttribute("bean") && beans
										.containsKey(((Element) currentNode)
												.getAttribute("bean")))) {
							// 该list子元素为引用bean
							String ref = ((Element) currentNode)
									.getAttribute("bean");
							collection.add(beans.get(ref));
						} else if (currentNode.getNodeName().equals("bean")) {
							// 该list子元素为内部bean
							collection.add(initBean(currentNode));
						}
					}
					value = collection;
				} else if (ParserHelper.containNode(property, "map")) {
					// 属性为map集合类型
					HashMap<String, Object> map = new HashMap<String, Object>();
					for (Node currentNode = property.getFirstChild()
							.getFirstChild(); currentNode != null; currentNode = currentNode
							.getNextSibling()) {
						if (currentNode.getNodeName().equals("entry")
								&& (((Element) currentNode).hasAttribute("key") && (((Element) currentNode)
										.hasAttribute("value-ref") && beans
										.containsKey(((Element) currentNode)
												.getAttribute("value-ref"))))) {
							// 该list子元素为引用bean
							String key = ((Element) currentNode)
									.getAttribute("key");
							String ref = ((Element) currentNode)
									.getAttribute("value-ref");
							map.put(key, beans.get(ref));
						}
					}
					value = map;
				} else if (ParserHelper.containNode(property, "props")) {
					// 属性为props属性类型
					Properties props = new Properties();
					for (Node currentNode = property.getFirstChild()
							.getFirstChild(); currentNode != null; currentNode = currentNode
							.getNextSibling()) {
						if (currentNode.getNodeName().equals("prop")
								&& ((Element) currentNode).hasAttribute("key")) {
							// 该list子元素为引用bean
							String key = ((Element) currentNode)
									.getAttribute("key");
							String propValue = currentNode.getTextContent();
							props.setProperty(key, propValue);
						}
					}
					value = props;
				}

				// 调用set方法,初始化bean的属性
				try {
					method.invoke(object, value);
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					e.printStackTrace();
				}
			}
		}

		// 若为构造函数注入
		if (constructorInit == true) {
			Class[] aClasses = {};
			Class[] classes = (Class[]) parameterTypes.toArray(aClasses);
			Object[] prams = (Object[]) parameters.toArray();
			try {
				object = c.getConstructor(classes).newInstance(prams);
			} catch (SecurityException e) {
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (InstantiationException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			}
		}

		if (object.getClass().getInterfaces().length == 0) {
			return object;
		} else {
			// 返回经过代理的bean
			return new ProxyHandler(object).getProxyInstance();
		}
	}

	// 获取hashMap中相应的bean
	public Object getBean(String id) {
		Object bean = beans.get(id);
		// 未初始化的bean,有可能为懒加载,也有可能没有此bean
		if (bean == null) {
			Element element = dom.getElementById(id);
			if (element.getTagName().equals("bean")
					&& element.hasAttribute("lazy-init")
					&& element.getAttribute("lazy-init").equals("true")) {
				// 确实为懒加载
				// 创建后,存入map中
				System.out.println("懒加载:" + id);
				bean = initBean(element);
				beans.put(element.getAttribute("id"), bean);
			} else {
				// 无此Bean的懒加载声明
				System.out.println("找不到此Bean");
			}
		}
		return bean;
	}

	// 检验是否为基本值类型或基本对象
	@SuppressWarnings("rawtypes")
	private boolean isPrimitive(String className) {
		Class clazz = null;
		try {
			clazz = Class.forName(className);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		String name = clazz.getName();
		if (clazz.isPrimitive() || name.equals("java.lang.String")
				|| name.equals("java.lang.Integer")
				|| name.equals("java.lang.Float")
				|| name.equals("java.lang.Double")
				|| name.equals("java.lang.Character")
				|| name.equals("java.lang.Integer")
				|| name.equals("java.lang.Boolean")
				|| name.equals("java.lang.Short")) {
			return true;
		} else {
			return false;
		}
	}

	// 通过字符串反射类型,增加了对基本类型的包装
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private Object getInstanceForName(String name, String value) {
		Class clazz = nameToClass(name);

		Object object = null;
		try {
			object = clazz.getConstructor(String.class).newInstance(value);
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		}
		return object;
	}

	//通过类型名返回基本类型Class(Class.forName()貌似不行)
	@SuppressWarnings("rawtypes")
	private Class nameToPrimitiveClass(String name) {
		Class clazz = null;
		if (name.equals("int")) {
			clazz = int.class;
		} else if (name.equals("char")) {
			clazz = char.class;
		} else if (name.equals("boolean")) {
			clazz = boolean.class;
		} else if (name.equals("short")) {
			clazz = short.class;
		} else if (name.equals("long")) {
			clazz = long.class;
		} else if (name.equals("float")) {
			clazz = float.class;
		} else if (name.equals("double")) {
			clazz = double.class;
		} else if (name.equals("byte")) {
			clazz = byte.class;
		} else {
			try {
				clazz = Class.forName(name);
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		}

		return clazz;
	}

	//通过类型名获取包装器类
	@SuppressWarnings("rawtypes")
	private Class nameToClass(String name) {
		Class clazz = null;
		if (name.equals("int")) {
			clazz = Integer.class;
		} else if (name.equals("char")) {
			clazz = Character.class;
		} else if (name.equals("boolean")) {
			clazz = Boolean.class;
		} else if (name.equals("short")) {
			clazz = Short.class;
		} else if (name.equals("long")) {
			clazz = Long.class;
		} else if (name.equals("float")) {
			clazz = Float.class;
		} else if (name.equals("double")) {
			clazz = Double.class;
		} else if (name.equals("byte")) {
			clazz = Byte.class;
		} else {
			try {
				clazz = Class.forName(name);
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		}

		return clazz;
	}
}

ParserHelper.java

package cn.seu.bingluo.ioc;

import org.w3c.dom.Node;
/*
 * By Bingluo 2012.8.17
 * cose.seu.edu.cn
 * Parser辅助方法
 */
public class ParserHelper {

	//查看Node中是否存在名为name的子节点
	public static boolean containNode(Node node,String name){
		for (Node currentNode = node.getFirstChild(); currentNode!=null; currentNode = currentNode.getNextSibling()) {
			if (currentNode.getNodeName().equals(name)) {
				return true;
			}
		}
		return false;
	}

	//返回名称对应的节点
	public static Node getNode(Node node, String name){
		for (Node currentNode = node.getFirstChild(); currentNode!=null; currentNode = currentNode.getNextSibling()) {
			if (currentNode.getNodeName().equals(name)) {
				return currentNode;
			}
		}
		return null;
	}
} 

 

ProxyHandler.java
package cn.seu.bingluo.ioc;

import java.lang.reflect.InvocationHandler;

/*
 * 代理类
 * 运用jdk动态代理实现,要求前提是被代理对象实现接口
 */
public class ProxyHandler implements InvocationHandler {
	// 存储所有切面
	private static HashMap<String, AspectInfo> aspectInfos = new HashMap<String, AspectInfo>();

	// 被代理的对象
	private Object target = null;

	public ProxyHandler(Object target) {
		this.target = target;
	}

	public static void addAspectInfo(AspectInfo aspectInfo) {
		aspectInfos.put(aspectInfo.getExpression(), aspectInfo);
	}

	// 获取代理实例
	public Object getProxyInstance() {
		if (target == null) {
			return null;
		}
		return Proxy.newProxyInstance(target.getClass().getClassLoader(),
				target.getClass().getInterfaces(), this);
	}

	// 获取代理实例
	public Object getProxyInstance(Object target) {
		if (target == null) {
			return null;
		}
		this.target = target;
		return Proxy.newProxyInstance(target.getClass().getClassLoader(),
				target.getClass().getInterfaces(), this);
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		ArrayList<AspectInfo> aspects = new ArrayList<AspectInfo>();
		Set<Entry<String, AspectInfo>> entrySet = aspectInfos.entrySet();
		Object result = null;

		//遍历切面列表,找到对应的切面
		for (Entry<String, AspectInfo> entry : entrySet) {
			AspectInfo aspectInfo = entry.getValue();
			Object adviceBean = aspectInfo.getAdviceBean();
			String expression = aspectInfo.getExpression();

			Pattern pattern = Pattern.compile(expression);
			Matcher matcher = pattern.matcher(target.getClass().getName() + "."
					+ method.getName());
			if (matcher.find()) {
				AspectInfo aspect = new AspectInfo();
				aspect.setAdviceBean(adviceBean);
				aspect.setBeforeMethod(aspectInfo.getBeforeMethod());
				aspect.setAroundMethod(aspectInfo.getAroundMethod());
				aspect.setAfterMethod(aspectInfo.getAfterMethod());
				aspects.add(aspect);
			}
		}

		// 执行before增强
		for (AspectInfo aspect : aspects) {
			Object adviceBean = aspect.getAdviceBean();
			if (aspect.getBeforeMethod() != null) {
				aspect.getBeforeMethod().invoke(adviceBean, new Object[]{});
			}
		}

		// 执行around增强
		Object aroundAdviceBean = target;
		Method aroundAdviceMethod = method;
		Object[] aroundAdviceArgs = args;
		for (AspectInfo aspect : aspects) {
			Object adviceBean = aspect.getAdviceBean();
			if (aspect.getAroundMethod() != null) {
				aroundAdviceArgs = new Object[] { new ProceedingJoinPoint(
						aroundAdviceBean, aroundAdviceMethod, aroundAdviceArgs) };
				aroundAdviceBean = adviceBean;
				aroundAdviceMethod = aspect.getAroundMethod();
			}
		}
		result = aroundAdviceMethod.invoke(aroundAdviceBean, aroundAdviceArgs);

		// 执行After增强
		for (AspectInfo aspect : aspects) {
			Object adviceBean = aspect.getAdviceBean();
			if (aspect.getAfterMethod() != null) {
				aspect.getAfterMethod().invoke(adviceBean, new Object[]{});
			}
		}
		return result;
	}

}

 

ProceedingJoinPoint.java

package cn.seu.bingluo.ioc;

import java.lang.reflect.InvocationTargetException;

/*
 * 用于处理AOP代理链时,封装相关信息作为统一参数进行传递
 */
public class ProceedingJoinPoint {
	private Object object;//被代理的对象
	private Method method;//被代理的方法
	private Object[] args;//方法相应的参数

	public ProceedingJoinPoint(Object object, Method method, Object[] args){
		this.object = object;
		this.method = method;
		this.args = args;
	}

	//执行目标函数
	public Object excute(){
		Object result = null;
		try {
			result = method.invoke(object, args);
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		return result;
	}
}
 

AspectInfo.java

package cn.seu.bingluo.ioc;

import java.lang.reflect.Method;

/*
 * 切面信息Bean
 * 每1个切面最多只有:
 * 1个切点expression
 * 1个增强bean
 * 1个前置增强、环绕增强、后置增强
 */
public class AspectInfo {
	private String expression = "";
	private Object adviceBean = null;
	private Method beforeMethod = null;
	private Method aroundMethod = null;
	private Method afterMethod = null;

	public AspectInfo(){

	}

	public AspectInfo(String expression, Object adviceBean,
			Method beforeMethod, Method aroundMethod, Method afterMethod) {
		setExpression(expression);
		setAdviceBean(adviceBean);
		setBeforeMethod(beforeMethod);
		setAroundMethod(aroundMethod);
		setAfterMethod(afterMethod);
	}

	public String getExpression() {
		return expression;
	}

	public void setExpression(String expression) {
		this.expression = expression;
	}

	public Object getAdviceBean() {
		return adviceBean;
	}

	public void setAdviceBean(Object adviceBean) {
		this.adviceBean = adviceBean;
	}

	public Method getBeforeMethod() {
		return beforeMethod;
	}

	public void setBeforeMethod(Method beforeMethod) {
		this.beforeMethod = beforeMethod;
	}

	public Method getAroundMethod() {
		return aroundMethod;
	}

	public void setAroundMethod(Method aroundMethod) {
		this.aroundMethod = aroundMethod;
	}

	public Method getAfterMethod() {
		return afterMethod;
	}

	public void setAfterMethod(Method afterMethod) {
		this.afterMethod = afterMethod;
	}
}

autumn.dtd

<?xml version="1.0" encoding="GBK"?>
<!ELEMENT beans (bean|aop-config)*>
<!ELEMENT bean (property*|constructor-arg*)>
<!ELEMENT aop-config (aspect*)>
<!ELEMENT aspect (pointcut,before?,around?,after?)>
<!ELEMENT property (bean|list|set|map|props)>
<!ELEMENT list (ref*)>
<!ELEMENT set (ref|bean)*>
<!ELEMENT map (entry*)>
<!ELEMENT props (prop*)>
<!ELEMENT prop (#PCDATA)>

<!ATTLIST bean id ID #IMPLIED>
<!ATTLIST bean class CDATA #REQUIRED>
<!ATTLIST bean value CDATA #IMPLIED>
<!ATTLIST property name CDATA #REQUIRED>
<!ATTLIST property value CDATA #IMPLIED>
<!ATTLIST property ref IDREF #IMPLIED>
<!ATTLIST constructor-arg type CDATA #IMPLIED>
<!ATTLIST constructor-arg value CDATA #IMPLIED>
<!ATTLIST constructor-arg ref IDREF #IMPLIED>
<!ATTLIST ref bean IDREF #REQUIRED>
<!ATTLIST entry key CDATA #REQUIRED>
<!ATTLIST entry value-ref IDREF #REQUIRED>
<!ATTLIST prop key CDATA #REQUIRED>
<!ATTLIST aspect ref IDREF #REQUIRED>
<!ATTLIST pointcut expression CDATA #REQUIRED>
<!ATTLIST before method CDATA #REQUIRED>
<!ATTLIST around method CDATA #REQUIRED>
<!ATTLIST after method CDATA #REQUIRED>

接下来,我们来测试一下框架功能是否实现!

先测试IOC,测试bean的装配,写个POJO类

TestIOCBean.java

package cn.seu.bingluo.ioc;

import java.util.Collection;

/*
 * By Bingluo 2012.8.17
 * cose.seu.edu.cn
 * 测试Bean
 */
public class TestIOCBean {
	private int a;
	private Integer aa;
	private String b;

	private TestIOCBean innerBean;
	private TestIOCBean outterBean;

	private Collection<String> collection;
	private Map<String, String> map;
	private Properties props;

	public TestIOCBean(){

	}

	public TestIOCBean(int a,String b,TestIOCBean oBeanTest) {
		this.setA(a);
		this.setB(b);
		this.setOutterBean(oBeanTest);
	}

	public Integer getA() {
		return a;
	}

	public void setA(int a){
		this.a = a;
	}

	public Integer getAa() {
		return aa;
	}

	public void setAa(Integer aa) {
		this.aa = aa;
	}

	public String getB() {
		return b;
	}

	public void setB(String b) {
		this.b = b;
	}

	public TestIOCBean getInnerBean() {
		return innerBean;
	}

	public void setInnerBean(TestIOCBean innerBean) {
		this.innerBean = innerBean;
	}

	public TestIOCBean getOutterBean() {
		return outterBean;
	}

	public void setOutterBean(TestIOCBean outterBean) {
		this.outterBean = outterBean;
	}

	public Collection<String> getCollection() {
		return collection;
	}

	public void setCollection(Collection<String> collection) {
		this.collection = collection;
	}

	public Map<String, String> getMap() {
		return map;
	}

	public void setMap(Map<String, String> map) {
		this.map = map;
	}

	public Properties getProps() {
		return props;
	}

	public void setProps(Properties props) {
		this.props = props;
	}
}

再写一个Service类,用于测试AOP功能,注意,框架AOP功能是用JDK动态代理实现的,故必须继承自某个接口:

ITestAOPBean.java

package cn.seu.bingluo.ioc;

/*
 * 必须被继承才能实现AOP代理
 */
public interface ITestAOPBean {
	public int shout();
}

TestAOPBean.java

package cn.seu.bingluo.ioc;

/*
 * 测试AOP功能
 * 用jdk动态代理实现,故必须继承接口
 */
public class TestAOPBean implements ITestAOPBean{
	private String name = "aop-test";

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public int shout() {
		System.out.println("Hello, My name is "+name);
		return 1;
	}
}

再为这个service写一个增强类,将该类中的方法织入service的shout()中。

Advice.java

package cn.seu.bingluo.ioc;

/*
 * 增强类
 * 用于测试AOP功能
 */
public class Advice {
	public void Before(){
		System.out.println("Before...");
	}

	public Object Around(ProceedingJoinPoint joinPoint){
		System.out.println("Before-around...");
		Object object = joinPoint.excute();
		System.out.println("After-around...");
		return object;
	}

	public void After(){
		System.out.println("After...");
	}
}

到这里,重点来了,我们就需要将bean配置起来了,建立xml文件:

config.xml(注意用dtd约束)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans SYSTEM "d:\\autumn.dtd">
<beans>
	<bean id="str1" class="java.lang.String" value="String: str1"/>
	<bean id="str2" class="java.lang.String" value="String: str2"/>

	<bean id="bean" class="cn.seu.bingluo.ioc.TestIOCBean" lazy-init="true">
		<property name="a" value="1000" />
		<property name="aa" value="999" />
		<property name="b" value="I'm lazy-init bean" />
		<property name="innerBean">
			<bean class="cn.seu.bingluo.ioc.TestIOCBean">
				<property name="a" value="1000" />
				<property name="aa" value="999" />
				<property name="b" value="I'm inner bean" />
				<property name="outterBean" ref="outterBean" />
				<property name="collection">
					<set>
						<ref bean="str1" />
						<bean class="java.lang.String" value="str3" />
					</set>
				</property>
			</bean>
		</property>
		<property name="collection">
			<list>
				<ref bean="str1" />
				<ref bean="str2" />
			</list>
		</property>
	</bean>

	<bean id="outterBean" class="cn.seu.bingluo.ioc.TestIOCBean">
		<property name="a" value="1000" />
		<property name="aa" value="999" />
		<property name="b" value="I'm outter bean" />
		<property name="map">
			<map>
				<entry key="s1" value-ref="str1" />
				<entry key="s2" value-ref="str2" />
			</map>
		</property>
		<property name="props">
			<props>
				<prop key="s3">im' props' value: s3</prop>
				<prop key="s4">im' props' value: s4</prop>
			</props>
		</property>
	</bean>

	<bean id="constructorInit" class="cn.seu.bingluo.ioc.TestIOCBean">
		<constructor-arg value="555" type="int" />
		<constructor-arg value="String" type="java.lang.String" />
		<constructor-arg ref="bean" />
	</bean>

	<bean id="shoutBean" class="cn.seu.bingluo.ioc.TestAOPBean" />

	<bean id="adviceBean" class="cn.seu.bingluo.ioc.Advice" />

	<!-- AOP配置 -->
	<aop-config>
		<!-- 定义切面 -->
		<aspect ref="adviceBean">
			<!-- 定义切点 -->
			<pointcut expression=".*.shout()" />
			<!-- 定义各类增强 -->
			<before method="Before" />
			<around method="Around" />
			<after method="After" />
		</aspect>
	</aop-config>
</beans>

最后,再写一个main函数驱动一下,就大功告成啦!

Driver.java

package cn.seu.bingluo.ioc;

import java.util.Iterator;

public class Driver {

	/**
	 * @param args
	 */

	@SuppressWarnings("rawtypes")
	public static void main(String[] args) {
		// 测试桩

		// 解析IOC配置文件
		ConfigManager configManager = new ConfigManager("config.xml");
		// 获取id为“bean”的Bean
		TestIOCBean beanTest = (TestIOCBean) configManager.getBean("bean");
		System.out.println(beanTest.getA() + ":" + beanTest.getAa() + ":"
				+ beanTest.getB());

		System.out.println(beanTest.getInnerBean().getB());
		System.out.println(beanTest.getInnerBean().getOutterBean().getB());

		String string = (String) configManager.getBean("str1");
		System.out.println(string);

		string = (String) configManager.getBean("str2");
		System.out.println(string);

		// 装配集合测试
		List<String> list = (List<String>) beanTest.getCollection();
		System.out.println(list.get(0));

		Set<String> set = (Set<String>) beanTest.getInnerBean().getCollection();
		for (Iterator it = set.iterator(); it.hasNext();) {
			System.out.println("value=" + it.next().toString());
		}

		TestIOCBean outterBeanTest = (TestIOCBean) configManager
				.getBean("outterBean");
		System.out.println(outterBeanTest.getMap().get("s1"));
		System.out.println(outterBeanTest.getProps().get("s3"));

		//测试构造函数注入
		TestIOCBean constructorBeanTest = (TestIOCBean) configManager
				.getBean("constructorInit");
		System.out.println(constructorBeanTest.getA()
				+ constructorBeanTest.getB()
				+ constructorBeanTest.getOutterBean().getAa());

		//测试AOP功能
		System.out.println("\n***************** AOP测试 *****************");
		ITestAOPBean testBean = (ITestAOPBean) configManager.getBean("shoutBean");
		testBean.shout();
	}
}

运行结果:

 

功能算是实现啦!

如果有发现什么问题或者不足的话,欢迎给我留言或者发送邮件。谢谢!

邮箱:bingluo#foxmail.com(#转为@)

转载于:https://my.oschina.net/cose/blog/73919

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值