前言
XML:通过Dom4j对XML进行解析和验证。
IOC:通过获取要创建对象的Class类型、构造函数后,通过反射来实现。
AOP:通过使用JDK动态代理和Cglib动态代理实现。
一、解析XML
1.1、解析bean标签
/**
* 解析bean标签
* @param xmlBean bean标签
*/
private void parseBeanDefinitionXML(Element xmlBean){
String beanId = xmlBean.attributeValue("id");
if (beanDefinitionMap.containsKey(beanId)) {
return;
}
String beanClass = xmlBean.attributeValue("class");
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setId(beanId);
beanDefinition.setClassName(beanClass);
List<Element> xmlConstructor = xmlBean.elements();
// 无参bean,则解析完成
if (UsualUtil.isNull(xmlConstructor)) {
beanDefinitionMap.put(beanId, beanDefinition);
return;
}
List<BeanDefinition.ConstructArg> constructArgs = new ArrayList<>();
// 解析参数
for (Element xmlConstructArg : xmlConstructor) {
// 目前仅解析constructor-arg
if ("constructor-arg".equals(xmlConstructArg.getName())) {
String typeClass = xmlConstructArg.attributeValue("type");
String value = xmlConstructArg.attributeValue("value");
String refName = xmlConstructArg.attributeValue("ref");
BeanDefinition.ConstructArg constructArg = new BeanDefinition.ConstructArg();
constructArg.setType(typeClass);
constructArg.setValue(value);
constructArg.setRef(refName);
// 非引用其他bean
if (UsualUtil.isNull(refName)) {
if (typeClass.endsWith("List")) {
Element xmlCollection = xmlConstructArg.elements().get(0);
String valueTypeClass = xmlCollection.attributeValue("value-type");
constructArg.setItemType(valueTypeClass);
List<String> itemValue = new ArrayList<>();
for (Element xmlItem : xmlCollection.elements()) {
itemValue.add(xmlItem.getStringValue());
}
constructArg.setItemValue(itemValue);
}
}
constructArgs.add(constructArg);
}
}
beanDefinition.setConstructArgs(constructArgs);
beanDefinitionMap.put(beanId, beanDefinition);
}
1.2、解析aspect标签
/**
* 解析aspect标签
* @param xmlAspect aspect标签
* @param useCglib 是否使用cglib
*/
private void parseAspectXML(Element xmlAspect, boolean useCglib) {
// <aop:config>
// <aop:aspect ref="aspect">
// <aop:before method="run" pointcut="execution(public void org.tree.aspect.AspectProcessor.before())"/>
// <aop:after method="run" pointcut="execution(public void org.tree.aspect.AspectProcessor.after())"/>
// </aop:aspect>
// </aop:config>
String refName = xmlAspect.attributeValue("ref");
if (aspectDefinitionMap.containsKey(refName)) {
return;
}
AspectDefinition aspectDefinition = new AspectDefinition();
aspectDefinition.setUseCglib(useCglib);
aspectDefinition.setRef(refName);
List<AspectDefinition.Advice> advices = new ArrayList<>();
for (Element xmlAdvice : xmlAspect.elements()) {
AspectDefinition.Advice advice = new AspectDefinition.Advice();
advice.setType(xmlAdvice.getName());
// execution(public void org.tree.aspect.AspectProcessor.before())
String pointcutStr = xmlAdvice.attributeValue("pointcut");
pointcutStr = pointcutStr.replace("execution", "");
pointcutStr = pointcutStr.substring(0, pointcutStr.length() - 1);
// public void org.tree.aspect.AspectProcessor.before()
String[] strings = pointcutStr.split(" ");
advice.setMethod(xmlAdvice.attributeValue("method"));
advice.setProxyMethod(strings[2].substring(strings[2].lastIndexOf('.') + 1, strings[2].length() - 2));
advice.setProxyClass(strings[2].substring(0, strings[2].lastIndexOf('.')));
advices.add(advice);
}
aspectDefinition.setAdvices(advices);
aspectDefinitionMap.put(refName, aspectDefinition);
}
二、加载Bean
加载Bean时,本文实现的是通过构造函数注入参数,所以无法解决循环依赖的问题。
浅说下发现构造函数循环依赖的原理:当要加载一个bean时,记录下当前bean的加载状态为“正在创建中”,准备好构造函数所需要的参数,如果参数是未加载的,则取加载其参数,当加载的参数发现自己正处于“正在创建中”的状态时,则此刻这两个bean之间发生循环依赖了。
2.1、getBean
/**
* 通过bean实例名字获取实例
* @param id bean实例名字
* @return bean实例
*/
public Object getBean(String id) throws Exception {
if (beanFactory.containsKey(id)) {
return beanFactory.get(id);
}
if (!beanDefinitionMap.containsKey(id)) {
return null;
}
BeanDefinition beanDefinition = beanDefinitionMap.get(id);
List<BeanDefinition.ConstructArg> constructArgs = beanDefinition.getConstructArgs();
if (UsualUtil.isNull(constructArgs)) {
// 创建bean前操作
if (beanPostProcessor != null) {
beanPostProcessor.preInitBean(objectFactory.get(id), id);
}
Object beanObj = Class.forName(beanDefinition.getClassName()).getConstructor().newInstance();
// 如果该bean被aop引用
beanObj = doEnhanceBean(beanDefinition, beanObj);
// 创建bean后操作
if (beanPostProcessor != null) {
beanPostProcessor.postInitBean(beanObj, id);
}
beanFactory.put(id, beanObj);
return beanObj;
}
return doCreateBean(beanDefinition);
}
2.2、doCreateBean
/**
* 创建bean
* @param beanDefinition bean标签
* @return bean实例
* @throws Exception 空
*/
private Object doCreateBean(BeanDefinition beanDefinition) throws Exception{
// 标记该bean正在创建实例中
objectFactory.put(beanDefinition.getId(), Class.forName(beanDefinition.getClassName()).getConstructor().newInstance());
List<BeanDefinition.ConstructArg> constructArgs = beanDefinition.getConstructArgs();
Class<?>[] paramTypes = new Class[constructArgs.size()];
Object[] paramValues= new Object[constructArgs.size()];
int paramIndex = 0;
for (BeanDefinition.ConstructArg constructArg : constructArgs) {
// 构造函数参数为引用
if (!UsualUtil.isNull(constructArg.getRef())) {
// 该引用bean已经创建实例
if (beanFactory.containsKey(constructArg.getRef())) {
Object refBeanObj = beanFactory.get(constructArg.getRef());
paramTypes[paramIndex] = refBeanObj.getClass();
paramValues[paramIndex] = refBeanObj;
paramIndex++;
// 该引用bean正在创建实例中,循环引用
} else if (objectFactory.containsKey(constructArg.getRef())) {
throw new Exception("Both id '" + beanDefinition.getId() + "' and '" + constructArg.getRef() + "' are circular reference");
// 该引用bean未创建实例
} else {
Object refBeanObj = doCreateBean(beanDefinitionMap.get(constructArg.getRef()));
paramTypes[paramIndex] = refBeanObj.getClass();
paramValues[paramIndex] = refBeanObj;
paramIndex++;
}
continue;
}
paramTypes[paramIndex] = Class.forName(constructArg.getType());
// 构造函数参数为非引用类型, 且是非集合类型
if (!(constructArg.getType().endsWith("List"))) {
paramValues[paramIndex++] = Class.forName(constructArg.getType()).getConstructor(String.class).newInstance(constructArg.getValue());
continue;
}
List<Object> objParamList = new ArrayList<>();
for (String itemValue : constructArg.getItemValue()) {
objParamList.add(Class.forName(constructArg.getItemType()).getConstructor(String.class).newInstance(itemValue));
}
paramValues[paramIndex++] = objParamList;
}
// 创建bean前操作
if (beanPostProcessor != null) {
beanPostProcessor.preInitBean(objectFactory.get(beanDefinition.getId()), beanDefinition.getId());
}
Object beanObj = Class.forName(beanDefinition.getClassName()).getConstructor(paramTypes).newInstance(paramValues);
// 如果该bean被aop引用
beanObj = doEnhanceBean(beanDefinition, beanObj);
// 创建bean后操作
if (beanPostProcessor != null) {
beanPostProcessor.postInitBean(beanObj, beanDefinition.getId());
}
beanFactory.put(beanDefinition.getId(), beanObj);
// 标记该bean没有正在创建
objectFactory.remove(beanDefinition.getId());
return beanObj;
}
三、增强Bean
3.1、doEnhanceBean
/**
* 创建增强bean
* @param beanDefinition bean标签
* @param beanObj bean对象
* @return 增强bean
* @throws Exception 空
*/
private Object doEnhanceBean(BeanDefinition beanDefinition, Object beanObj) throws Exception {
if (aspectDefinitionMap.containsKey(beanDefinition.getId())) {
AspectDefinition aspectDefinition = aspectDefinitionMap.get(beanDefinition.getId());
for (AspectDefinition.Advice advice : aspectDefinition.getAdvices()) {
// 增强beanObj
beanObj = doCreateProxy(beanObj, advice.getMethod(), advice.getProxyClass(), advice.getProxyMethod()
, "before".equals(advice.getType()), aspectDefinition.isUseCglib());
}
}
return beanObj;
}
3.2、doCreateProxy
/**
* 创建代理对象
* @param beanObj bean实例
* @param joinPointMethod 要代理的bean方法
* @param strProxyClass 代理类
* @param strProxyMethod 代理类的方法
* @param isBefore 通知类型
* @param useCglib 是否使用cglib
* @return 代理对象
* @throws Exception 空
*/
private Object doCreateProxy(Object beanObj, String joinPointMethod, String strProxyClass, String strProxyMethod
, boolean isBefore, boolean useCglib) throws Exception {
Class<?> clazz = Class.forName(strProxyClass);
Object proxyObject = clazz.getConstructor().newInstance();
Method proxyMethod = clazz.getMethod(strProxyMethod);
// 如果使用cglib动态代理
if (useCglib) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(beanObj.getClass());
/*
* 设置被代理类执行方法时的逻辑
* o 被代理类生成的对象实例(子类)
* method 被代理类的方法
* args 方法的参数
* methodProxy 被代理类的方法的代理方法
*/
enhancer.setCallback((MethodInterceptor) (o, method, args, methodProxy) -> {
// 当方法是我们要代理的方法时
if (method.getName().equals(joinPointMethod)) {
if (isBefore) {
proxyMethod.invoke(proxyObject);
}
// 调用父类的方法
methodProxy.invokeSuper(o, args); // 使用beanObj会报错,因为参数需要的是生成的子类
if (!isBefore) {
proxyMethod.invoke(proxyObject);
}
} else { // 如果不写,则是全放空(由于生成的是子类,其他方法全空,不调用父类的【被代理类】)
methodProxy.invokeSuper(o, args); // 调用父类的方法
}
return o;
});
return enhancer.create();
}
/*
* clazz 加载被代理类的加载器
* interfaces 被代理类实现的所有接口
* 增强方法
* o 被代理类的对象实例
* method 被代理类实现的所有接口的方法,且要执行
* args 方法需要的参数
*/
// 代理一个类,该类通过loader加载,且实现interfaces接口
return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), beanObj.getClass().getInterfaces(), (o, method, args) -> {
// 当方法为我们要代理的方法时,执行特定增强
if (method.getName().equals(joinPointMethod)) {
if (isBefore) {
proxyMethod.invoke(proxyObject);
}
// 调用被代理类实际的方法
method.invoke(beanObj, args); // 这里写beanObj不报错是因为它是AspectInterface的子类, 但不能写o,会死循环(调用了代理的自己,又再次调用)
if (!isBefore) {
proxyMethod.invoke(proxyObject);
}
} else {
method.invoke(beanObj, args);
}
// 返回值就是代理类执行代理方法的返回值
return o;
});
四、类图
gitee地址:https://gitee.com/sir-tree/my-spring.git