spring学习二:根据spring原理自己写个spring

请先看我另一篇文章:“Spring学习一:IOC(控制反转)和AOP(面向切面)的xml配置和注解方式”中大概知道他的简单用法

那我自己想写一个简单sping,注解的方式以后再写

方式:1.解析xml配置

            2.使用java的反射机制生产动态代理对象

            3.扫描类上的注解,再用反射(没写)

代码如下(简单实现,重原理轻代码,不喜勿喷)

xml配置我就直接用我上一篇spring-test的配置了,代码也用上一篇的,但解析的时候是用自己写的,没有用调用任何spring API代码

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation=" 
                http://www.springframework.org/schema/beans 
                http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
                http://www.springframework.org/schema/context 
                http://www.springframework.org/schema/context/spring-context-3.0.xsd 
                http://www.springframework.org/schema/mvc 
                http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
                http://www.springframework.org/schema/aop  
                http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
                ">
    <!-- 注解支持,为了让我们可以使用注解创建bean -->
	<context:annotation-config />
	<!--设置要扫描的包的位置 -->
    <context:component-scan   base-package="com.eyugame.test" />
	<!-- 支持aop注解 -->
	<aop:aspectj-autoproxy />
	<aop:config >
		<!-- 配置aop触发调用的类是myService也就是下面对应的MyServiceImpl -->
		<aop:aspect id="spect" ref="myAop">
			<!-- 配置调用com.eyugame.test.MyBean的toDo()方法的时候触发aop -->
			<aop:pointcut id="target"
				expression="execution(* com.eyugame.test.MyBean.toDo(..))" />
			<!-- 执行前调用,调用方法为doBefore -->
			<aop:before pointcut-ref="target" method="doBefore()" />
			<!-- 执行后调用,调用方法为doAfter -->
			<aop:after pointcut-ref="target" method="doAfter()" />
			<!-- 返回时调用,调用方法doReturn -->
			<aop:after-returning pointcut-ref="target"
				method="doReturn()" />
			<!-- 抛出异常时候调用,调用方法doReturn -->
			<aop:after-throwing pointcut-ref="target" method="doThrowing()"
				throwing="ex" />
			<!-- 注意 aop:aroup在新版本spring好像失效,坑我 -->
			<!-- <aop:around pointcut-ref="businessService" method="doAround"/> -->
		</aop:aspect>
	</aop:config>
	<bean id="myAop" class="com.eyugame.test.MyAop"></bean>
	<bean id="depedecyBean" class="com.eyugame.test.DependencyBean"></bean>
	<!-- 依赖注入1构造器注入 -->
	<bean id="myBean" class="com.eyugame.test.MyBean">
		<constructor-arg ref="depedecyBean"></constructor-arg>
	</bean>
	<!-- 依赖注入2设值注入 -->
	<bean id="myBean2" class="com.eyugame.test.MyBean2">
		<!-- 名称要跟类里面要注入的类的名字一致 -->
		<property name="iDependency" ref="depedecyBean"></property>
	</bean>
	<!-- 注解Aop -->
	<bean id="myAop2" class="com.eyugame.test.MyAop2"></bean>
</beans>

代码如下

package com.eyugame.test.context;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

/**
 * 自定义的解析xml
 * 
 * @author k560
 * 
 */

public class MyApplicationContext {
	/* 配置符号 */
	private static String LINK = "/";
	private static String BEAN = "bean";
	private static String BEAN_ID = "id";
	private static String BEAN_REF = "ref";
	private static String BEAN_CONSTROCTOR_ARG = "constructor-arg";
	private static String BEAN_PROPERTY = "property";
	private static String BEAN_CLASS = "class";
	private static String BEAN_NAME = "name";

	private static String AOP_CONFIG = "aop:config";
	private static String AOP_ASPECT = "aop:aspect";
	private static String AOP_POINTCUT = "aop:pointcut";
	private static String AOP_BEFORE = "aop:before";
	private static String AOP_AFTER = "aop:after";
	private static String AOP_AFTER_RETURNING = "aop:after-returning";
	private static String AOP_AFTER_THRWOING = "aop:after-throwing";

	private static String METHOD = "method";
	private static String EXPRESSION = "expression";
	/* 用来储存beanID,跟class所在位置 */
	private Map<String, Entry> beanMap;
	private IAop aop;

	/* 构造方法 */
	public MyApplicationContext(String path) {
		beanMap = new HashMap<String, Entry>();
		aop = new Aop();
		init(path);
	}

	/* 根据ID获取bean */
	public Object getBean(String beanId) {
		try {
			Entry entry = beanMap.get(beanId);
			MyInvocationHandler invo = new MyInvocationHandler(aop);
			if (entry.constructors != null && !entry.constructors.isEmpty()) {
				/* 构造器注入 */
				int size = entry.constructors.size();
				Object[] params = new Object[size];
				for (int i = 0; i < size; i++) {
					Entry en = entry.constructors.get(i);
					if (en.constructors == null || en.constructors.isEmpty()) {
						Class<?> clazz = Class.forName(beanMap.get(en.id).className);
						params[i] = invo.getInstance(clazz);
					} else {
						params[i] = this.getBean(en.id);
					}
				}
				Object obj = invo.getInstance(Class.forName(entry.className), params);
				return obj;
			}
			Object obj = invo.getInstance(Class.forName(entry.className));
			if (entry.properties != null && !entry.properties.isEmpty()) {
				int pSize = entry.properties.size();
				for (int i = 0; i < pSize; i++) {
					Entry en = entry.properties.get(i);
					Object[] params = new Object[pSize];
					if (en.properties == null || en.properties.isEmpty()) {
						Class<?> clazz = Class.forName(beanMap.get(en.id).className);
						params[i] = invo.getInstance(clazz);
					} else {
						params[i] = this.getBean(en.id);
					}
					this.setPro(obj, en.name, params[i]);
				}
			}
			return obj;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/* 反射方式方法注入 */
	public void setPro(Object bean, String name, Object param) throws IntrospectionException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
		PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
		for (PropertyDescriptor pd : propertyDescriptors) {
			String name2 = pd.getName();
			if (name.equals(name2)) {
				Method method = pd.getWriteMethod();
				if (!name.equalsIgnoreCase("class")) {
					method.invoke(bean, param);
				}
			}
		}
	}

	/* 初始化 */
	private void init(String path) {
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder documentBuilder;
		try {
			documentBuilder = dbf.newDocumentBuilder();
			InputStream inputStrem = this.getClass().getResourceAsStream(LINK + path);
			Document doc = documentBuilder.parse(inputStrem);
			NodeList nList = doc.getElementsByTagName(BEAN);
			int length = nList.getLength();
			for (int i = 0; i < length; i++) {
				Element node = (Element) nList.item(i);
				NodeList constructors = node.getElementsByTagName(BEAN_CONSTROCTOR_ARG);
				NodeList pros = node.getElementsByTagName(BEAN_PROPERTY);
				String id = node.getAttributes().getNamedItem(BEAN_ID).getNodeValue();
				String className = node.getAttributes().getNamedItem(BEAN_CLASS).getNodeValue();
				Entry entry = new Entry(id);
				entry.className = className;
				int cLength = constructors.getLength();
				if (cLength > 0) {
					List<Entry> cList = new ArrayList<Entry>();
					for (int j = 0; j < cLength; j++) {
						String key = constructors.item(j).getAttributes().getNamedItem(BEAN_REF).getNodeValue();
						Entry cEntry = new Entry(key);
						cList.add(cEntry);
					}
					entry.constructors = cList;
				}
				int pLength = pros.getLength();
				if (pLength > 0) {
					List<Entry> pList = new ArrayList<Entry>();
					for (int j = 0; j < pLength; j++) {
						String key = pros.item(j).getAttributes().getNamedItem(BEAN_REF).getNodeValue();
						String name = pros.item(j).getAttributes().getNamedItem(BEAN_NAME).getNodeValue();
						Entry pEntry = new Entry(key);
						pEntry.name = name;
						pList.add(pEntry);
					}
					entry.properties = pList;
				}
				beanMap.put(id, entry);
			}
			NodeList aopList = doc.getElementsByTagName(AOP_CONFIG);
			int aopLength = aopList.getLength();
			/* aop解析 */
			for (int i = 0; i < aopLength; i++) {
				Element aopNode = (Element) aopList.item(i);
				NodeList aceList = aopNode.getElementsByTagName(AOP_ASPECT);
				int aLength = aceList.getLength();
				for (int j = 0; j < aLength; j++) {
					String key = aceList.item(i).getAttributes().getNamedItem(BEAN_REF).getNodeValue();
					String className = this.beanMap.get(key).className;
					Element node = (Element) aceList.item(i);
					NodeList nn = node.getElementsByTagName(AOP_POINTCUT);
					String expression = nn.item(0).getAttributes().getNamedItem(EXPRESSION).getNodeValue();
					String before = node.getElementsByTagName(AOP_BEFORE).item(0).getAttributes().getNamedItem(METHOD).getNodeValue();
					String after = node.getElementsByTagName(AOP_AFTER).item(0).getAttributes().getNamedItem(METHOD).getNodeValue();
					String returning = node.getElementsByTagName(AOP_AFTER_RETURNING).item(0).getAttributes().getNamedItem(METHOD).getNodeValue();
					String throwing = node.getElementsByTagName(AOP_AFTER_THRWOING).item(0).getAttributes().getNamedItem(METHOD).getNodeValue();
					this.aop.addAfter(new Target(className, after, expression));
					this.aop.addBeafore(new Target(className, before, expression));
					this.aop.addReturn(new Target(className, returning, expression));
					this.aop.addThrow(new Target(className, throwing, expression));
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}

/* 用来储存bean的信息 */
class Entry {
	/* bean的id */
	String id;
	/* bean的名称 */
	String name;
	/* bean 的类命 */
	String className;
	/* 构造器注入参数bean */
	List<Entry> constructors;
	/* 方法注入的参数 */
	List<Entry> properties;

	public Entry(String id) {
		this.id = id;
	}

}

/**
 * cglib动态代理
 * 
 */
class MyInvocationHandler implements MethodInterceptor {

	private IAop aop;

	private Object target;

	public MyInvocationHandler() {
		super();
	}

	public MyInvocationHandler(IAop aop) {
		super();
		this.aop = aop;
		this.aop.setInvo(this);
	}

	public Object getInstanceForObject(Object target) {
		this.target = target;
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(this.target.getClass());
		// 回调方法
		enhancer.setCallback(this);
		// 创建代理对象
		return enhancer.create();
	}

	/**
	 * 生产代理对象
	 * 
	 * @param T
	 *            要代理的类
	 * @param clazzs
	 *            参数类型
	 * @param params
	 *            参数列表
	 * @return
	 */
	public <T> T getInstance(Class<?> T, Class<?>[] clazzs, Object[] params) {
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(T);
		// 回调方法
		enhancer.setCallback(this);
		// 创建代理对象
		@SuppressWarnings("unchecked")
		T target = (T) enhancer.create(clazzs, params);
		this.target = target;
		return target;
	}

	/**
	 * 生产代理对象
	 * 
	 * @param T
	 *            要代理的类
	 * @param params
	 *            参数列表
	 * @return
	 */
	public <T> T getInstance(Class<?> T, Object[] params) {
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(T);
		// 回调方法
		enhancer.setCallback(this);
		Constructor<?>[] ts = T.getConstructors();
		for (Constructor<?> constructor : ts) {
			Class<?>[] clazzs = constructor.getParameterTypes();
			try {
				@SuppressWarnings("unchecked")
				T target = (T) enhancer.create(clazzs, params);
				this.target = target;
				return target;
			} catch (Exception e) {
				continue;
			}
		}
		return null;
	}

	/**
	 * 生产代理对象
	 * 
	 * @param T
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public <T> T getInstance(Class<?> T) {
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(T);
		// 回调方法
		enhancer.setCallback(this);
		// 创建代理对象
		T target = (T) enhancer.create();
		this.target = target;
		return target;
	}

	/**
	 * 面向切面AOP
	 */
	public Object intercept(Object obj, Method method, Object[] params, MethodProxy proxy) throws Throwable {
		if (aop != null) {
			String className = obj.getClass().getName();
			String methodName = method.getName();
			try {
				aop.doBefore(className, methodName, params);
				proxy.invokeSuper(obj, params);
				aop.doAfter(className, methodName, params);
				aop.doReturn(className, methodName, params);
			} catch (Throwable e) {
				e.printStackTrace();
				aop.dotThrow(className, methodName, params);
			}
		} else {
			System.out.println(method.getName());
			proxy.invokeSuper(obj, params);
		}
		return null;
	}

}

/* aop */
class Aop implements IAop {
	/* 执行前调用 */
	private List<Target> beaforeList;
	/* 执行后调用 */
	private List<Target> afterList;

	private List<Target> returnList;

	private List<Target> throwList;

	private MyInvocationHandler invo;

	public Aop() {
		this.beaforeList = new ArrayList<Target>();
		this.afterList = new ArrayList<Target>();
		this.returnList = new ArrayList<Target>();
		this.throwList = new ArrayList<Target>();
	}

	public void setInvo(MyInvocationHandler invo) {
		this.invo = invo;
	}

	public void addBeafore(Target target) {
		this.beaforeList.add(target);
	}

	public void addAfter(Target target) {
		this.afterList.add(target);
	}

	public void addReturn(Target target) {
		this.returnList.add(target);
	}

	public void addThrow(Target target) {
		this.throwList.add(target);
	}

	public void doBefore(String className, String methodName, Object[] params) {
		for (Target target : beaforeList) {
			target.todo(className, methodName, params, invo);
		}
	}

	public void doAfter(String className, String methodName, Object[] params) {
		for (Target target : afterList) {
			target.todo(className, methodName, params, invo);
		}
	}

	public void doReturn(String className, String methodName, Object[] params) {
		for (Target target : returnList) {
			target.todo(className, methodName, params, invo);
		}
	}

	public void dotThrow(String className, String methodName, Object[] params) {
		for (Target target : throwList) {
			target.todo(className, methodName, params, invo);
		}
	}

}

/* 记录要进行aop处理的类名,方法名, */
class Target {
	/**
	 * aop对象
	 */
	String aopName;
	/**
	 * aop调用非方法
	 */
	String methodName;
	/**
	 * 表达式
	 */
	String execution;

	public Target(String aopName, String methodName, String execution) {
		super();
		this.aopName = aopName;
		this.methodName = methodName;
		this.execution = execution;
	}

	public void todo(String className, String methodName, Object[] params, MyInvocationHandler invo) {
		if (this.isTrue(className, methodName, params)) {
			try {
				Class<?> aopClass = Class.forName(this.aopName);
				Object aop = invo.getInstance(aopClass);
				Method method = aopClass.getMethod(this.methodName.replace("()", ""));
				method.invoke(aop, new Object[] {});
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 解析execution是否匹配 我直接写死了
	 */
	public boolean isTrue(String className, String methodName, Object[] params) {
		if (className.contains("com.eyugame.test.MyBean$$") && methodName.equals("toDo")) {
			return true;
		}
		return false;
	}

}

/* AOP接口 */
interface IAop {
	void setInvo(MyInvocationHandler invo);

	void doBefore(String className, String methodName, Object[] params);

	void doAfter(String className, String methodName, Object[] params);

	void doReturn(String className, String methodName, Object[] params);

	void dotThrow(String className, String methodName, Object[] params);

	void addBeafore(Target target);

	void addAfter(Target target);

	void addReturn(Target target);

	void addThrow(Target target);

}



测试

package com.eyugame.test.context;

import com.eyugame.test.MyBean;
import com.eyugame.test.MyBean2;

public class Test {
	public static void main(String[] args) {

		MyApplicationContext context = new MyApplicationContext("config/spring/spring-test.xml");
		/*构造器注入,aop*/
		System.out.println("myBean将会有aop-----------");
		MyBean myBean = (MyBean) context.getBean("myBean");
		myBean.toDo();
		
		/*注册方法注入*/
		System.out.println("myBean2没有aop,因为没有配置------------");
		MyBean2 myBean2 = (MyBean2) context.getBean("myBean2");
		myBean2.toDo();
	}

}



运行结果跟我 使用spring 一样,有没有

 


评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值