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

来源:互联网 发布:淘宝创想电玩 编辑:程序博客网 时间:2024/05/29 19:35

请先看我另一篇文章:“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 一样,有没有

 


3 0
原创粉丝点击