请先看我另一篇文章:“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 一样,有没有
spring学习二:根据spring原理自己写个spring
原文地址:http://blog.csdn.net/h348592532/article/details/45601551