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 一样,有没有

时间: 2024-07-29 14:26:59

spring学习二:根据spring原理自己写个spring的相关文章

spring学习(二) ———— AOP之AspectJ框架的使用

前面讲解了spring的特性之一,IOC(控制反转),因为有了IOC,所以我们都不需要自己new对象了,想要什么,spring就给什么.而今天要学习spring的第二个重点,AOP.一篇讲解不完,所以这篇文章主要介绍一下什么是AOP,如何去理解AOP.理解完之后,在spring中如何使用AspectJ AOP框架的.看得懂,写的出spring配置的那么就学的差不多了.加油.建议都自己手动实现一遍,这样才能更好的理解. --WH 一.什么是AOP? AOP:面向切面编程,采用横向抽取机制,取代了传

Spring学习(二)--装配Bean

一.Spring装配机制 Spring提供了三种主要的装配机制: 1.在XML中进行显示配置 2.在Java中进行显示配置 3.隐式的bean发现机制和自动装配--自动化装配bean Spring可以通过注解来进行自动装配(无需再手动写配置文件),Spring从两个角度实现自动化装配: 1.组件扫描(component scanning):Spring会自动发现应用上下文中所创建的bean; 2.自动装配(autowiring):Spring自动满足bean之间的依赖;--以CD及CD播放器为示

Spring学习二、HelloSpring与IOC创建对象方式

三.HelloSpring 配置文件 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www

Spring学习(二)

Spring配置 查看配置文件中的标签: 可以看到常用的就只有四个标签! 1.别名(alias) 如果添加了别名,我们也可以使用别名获取到这个对象 <alias name="user" alias="userNew"/> 2.Bean的配置 id:bean的唯一标识符,也就是相当于我们学的对象名 class:bean 对象对应的全限定名:包名 + 类型 name:也是别名,而且可以提示去多个别名 <bean id="user"

浅谈Spring(二)IOC原理

一.引言 我们都知道,在采用面向对象方法设计的软件系统中,它的底层实现都是由N个对象组成的,所有的对象通过彼此的合作,最终实现系统的业务逻辑.举例:如果我们打开机械式手表的后盖,就会发现其是由N个齿轮组成,各个齿轮分别带动时针.分针和秒针顺时针旋转,从而在表盘上产生正确的时间.在这样的齿轮组中,如果有一个齿轮出了问题,就可能会影响到整个齿轮组的正常运转.齿轮组中齿轮之间的啮合关系,与软件系统中对象之间的耦合关系非常相似.对象之间的耦合关系是无法避免的,也是必要的,这是协同工作的基础.现在,伴随着

spring 学习二 @RequestMapping

RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上.用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径. RequestMapping注解有六个属性,下面我们把她分成三类进行说明. 1. value, method: value:     指定请求的实际地址,指定的地址可以是URI Template 模式(后面将会说明):     @RequestMapping(value={"/foo","/bar"}).  // 可以指定多

不错的Spring学习笔记(转)

Spring学习笔记(1)----简单的实例 ---------------------------------   首先需要准备Spring包,可从官方网站上下载.   下载解压后,必须的两个包是spring.jar和commons-logging.jar.此外为了便于测试加入了JUnit包.   在Myeclipse中创建Java项目.   编写一个接口类,为了简单,只加入了一个方法.   Java代码   1.package com.szy.spring.interfacebean;  

Spring系列之AOP的原理及手动实现

目录 Spring系列之IOC的原理及手动实现 Spring系列之DI的原理及手动实现 引入 到目前为止,我们已经完成了简易的IOC和DI的功能,虽然相比如Spring来说肯定是非常简陋的,但是毕竟我们是为了理解原理的,也没必要一定要做一个和Spring一样的东西.到了现在并不能让我们松一口气,前面的IOC和DI都还算比较简单,这里要介绍的AOP难度就稍微要大一点了. tips 本篇内容难度较大,每一步都需要理清思路,可能需要多看几遍,多画类图和手动实现更容易掌握. AOP 什么是AOP Asp

spring 自定义标签 学习二

在上篇中写的只支持写属性,不支持标签property的写法,但是如果有时候我们还想做成支持 property的用法,则可以在xsd中增加spring 自带的xsd引用 修改xsd文件如下: <?xml version="1.0"encoding="UTF-8"?> <xsd:schema xmlns="http://www.ruishenh.com/custom/myTest" xmlns:xsd="http://ww