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