MyApplicationContext.java
package com.lagou.edu.factory;
import com.lagou.edu.annotation.MyAutowired;
import com.lagou.edu.annotation.MyComponent;
import com.lagou.edu.annotation.MyTransactional;
import com.lagou.edu.utils.StringUtils;
import org.springframework.beans.factory.annotation.Qualifier;
import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* @author sunli
*/
public class MyApplicationContext {
/**
* 自定义IoC容器
*/
private Map<String, Object> instanceMap = new HashMap<>();
/**
* 声明式事务用代理对象工厂
*/
private ProxyFactory proxyFactory;
/**
* 根据key取得自定义IoC容器中的实例化对象
*
* @param id 自定义IoC容器的key
* @return 实例化对象
*/
public Object getBean(String id) {
return instanceMap.get(id);
}
/**
* 创建指定包名下类的实例化对象,并放入自定义IoC容器
*
* @param packageName 包名
*/
public void createBean(String packageName) throws Exception {
// 获取指定包名下所有类的全限定名
Set<String> classNames = getClassName(packageName, true);
// 获取类加载器,用来加载包内类文件
ClassLoader loader = Thread.currentThread().getContextClassLoader();
if (classNames != null) {
for (String className : classNames) {
doCreateBean(loader.loadClass(className));
}
}
}
/**
* 使用加载的类创建实例化对象
*
* @param clazz 用来实例化对象的类
*/
private void doCreateBean(Class<?> clazz) throws Exception {
Boolean hasMyComponent;
String key;
Object instance;
/* 1 不实例化注解和接口,只实例化类 */
if (clazz.isAnnotation() || clazz.isInterface()) {
return;
}
/* 2 获取该类所有注解,过滤需要IoC的自定义注解的类(@MyComponent,@MyService,@MyRepository),然后创建实例化对象 */
Annotation[] annotations = clazz.getAnnotations();
for (Annotation annotation : annotations) {
hasMyComponent = false;
/* 2.1 过滤@MyComponent */
if (annotation.annotationType().equals(MyComponent.class)) {
hasMyComponent = true;
} else {
for (Annotation subAnnotation : annotation.annotationType().getAnnotations()) {
// 过滤MyComponent的别名注解@MyService、@MyRepository
if (subAnnotation.annotationType().equals(MyComponent.class)) {
hasMyComponent = true;
break;
}
}
}
/* 2.2 自定义注解的场合,进行实例化 */
if (hasMyComponent) {
/* 2.2.1 IoC容器中已经创建实例化对象的场合,退出 */
if (hasBeanInstance(clazz)) {
return;
}
/* 2.2.2 获取自定义注解中value的值,作为IoC容器中的key */
key = (String) annotation.getClass().getDeclaredMethod("value").invoke(annotation);
// 如果没有设置value,就使用类名(小写首字母)
if (StringUtils.isEmpty(key)) {
key = StringUtils.lowerFirst(clazz.getSimpleName());
}
/* 2.2.3 获取该类实例化对象,存入自定义的IoC容器 */
instance = clazz.getDeclaredConstructor().newInstance();
instanceMap.put(key, instance);
/* 2.2.4 【直播视频要求】该类实现接口的场合,再将接口全限定名作为key放入容器,但实例化对象相同 */
for (Class<?> interfaceClass : clazz.getInterfaces()) {
instanceMap.put(interfaceClass.getName(), instance);
}
break;
}
}
}
/**
* 自动注入bean对象
*
* @throws IllegalAccessException
*/
public void autowireBean() throws IllegalAccessException {
for (Map.Entry<String, Object> map : instanceMap.entrySet()) {
Object instance = map.getValue();
populateBean(instance);
}
}
/**
* 维护对象属性依赖关系
*
* @throws IllegalAccessException
*/
private void populateBean(Object instance) throws IllegalAccessException {
/* 1 获取实例化对象的属性,并完成属性对象赋值 */
Field[] fields = instance.getClass().getDeclaredFields();
for (Field field : fields) {
Boolean hasAutowired = false;
Boolean hasQualifier = false;
/* 1.1 获取该属性所有注解,过滤需要赋值的对象(@MyAutowired) */
for (Annotation annotation : field.getAnnotations()) {
if (annotation.annotationType().equals(MyAutowired.class)) {
hasAutowired = true;
// 判断是否需要根据名称赋值
if (annotation.annotationType().equals(Qualifier.class)) {
hasQualifier = true;
}
break;
}
}
/* 1.2 需要赋值的场合,先使用key查找自定义IoC容器中的实例化对象,然后完成注入操作 */
if (hasAutowired) {
// 打开属性访问权限
field.setAccessible(true);
// 该属性已经注入过的场合,退出
if (field.get(instance) != null) {
return;
}
String id;
Object bean;
/* 1.2.1 获取key */
if (hasQualifier) {
// 需要按照名称查找的场合,获取名称
id = field.getAnnotation(Qualifier.class).value();
} else {
// 以外的场合,使用类型查找
id = StringUtils.lowerFirst(field.getType().getSimpleName());
}
/* 1.2.2 根据key获取自定义IoC容器中的实例化对象 */
bean = getBean(id);
/* 1.2.3 【直播视频要求】如果以上步骤没有查找到(该属性为接口类型),则使用接口全限定名称查找 */
if (bean == null) {
id = field.getType().getName();
bean = getBean(id);
}
/* 1.2.4 完成注入操作 */
field.set(instance, bean);
// 关闭属性访问权限
field.setAccessible(false);
/* 1.2.5 【直播视频要求】使用递归方式维护多层依赖关系 */
populateBean(field);
}
}
}
/**
* 创建处理事务的代理对象,然后替换自定义IoC容器中原对象
*/
public void createTransactionProxyBean() {
Object proxyBean;
// 获取创建声明式事务用代理对象的工厂
if (proxyFactory == null) {
proxyFactory = (ProxyFactory) getBean("proxyFactory");
}
for (Map.Entry<String, Object> map : instanceMap.entrySet()) {
Object instance = map.getValue();
proxyBean = doCreateTransactionProxyBean(instance);
// 替换自定义IoC容器中原对象
instanceMap.put(map.getKey(), proxyBean);
}
}
/**
* 根据实例化对象创建处理事务的代理对象
*
* @param instance 实例化对象
* @return 返回代理对象
*/
private Object doCreateTransactionProxyBean(Object instance) {
/* 1 获取声明式事务注解,没有的场合,退出 */
Annotation myTransactional = instance.getClass().getAnnotation(MyTransactional.class);
if (myTransactional == null) {
return null;
}
/* 2【直播视频要求】该实例实现接口的场合使用jdk原生动态代理技术,否则使用cglib方式生成代理对象,最后替换原对象 */
Class<?>[] interfaces = instance.getClass().getInterfaces();
if (interfaces != null && interfaces.length > 0) {
return proxyFactory.getJdkProxy(instance);
} else {
return proxyFactory.getCglibProxy(instance);
}
}
/**
* 检查是否已创建该类实例
*
* @param clazz 需要检查的类
* @return 检查结果
*/
private Boolean hasBeanInstance(Class<?> clazz) {
for (Map.Entry<String, Object> map : instanceMap.entrySet()) {
// 通过比较实例化对象类名来确定容器中是否创建过
if (map.getValue().getClass().getName().equals(clazz.getName())) {
return true;
}
}
return false;
}
/**
* 获取某包下所有类
*
* @param packageName 包名
* @param isRecursion 是否遍历子包
* @return 类的完整名称
*/
private Set<String> getClassName(String packageName, boolean isRecursion) {
Set<String> classNames = null;
ClassLoader loader = Thread.currentThread().getContextClassLoader();
String packagePath = packageName.replace(".", "/");
URL url = loader.getResource(packagePath);
if (url != null) {
String protocol = url.getProtocol();
if (protocol.equals("file")) {
classNames = getClassNameFromDir(url.getPath(), packageName, isRecursion);
} else if (protocol.equals("jar")) {
// JarFile jarFile = null;
// try {
// jarFile = ((JarURLConnection) url.openConnection()).getJarFile();
// } catch (Exception e) {
// e.printStackTrace();
// }
//
// if (jarFile != null) {
// getClassNameFromJar(jarFile.entries(), packageName, isRecursion);
// }
}
} else {
/*从所有的jar包中查找包名*/
// classNames = getClassNameFromJars(((URLClassLoader) loader).getURLs(), packageName, isRecursion);
}
return classNames;
}
/**
* 从项目文件获取某包下所有类
*
* @param filePath 文件路径
* @param packageName 包名
* @param isRecursion 是否遍历子包
* @return 类的完整名称
*/
private Set<String> getClassNameFromDir(String filePath, String packageName, boolean isRecursion) {
Set<String> className = new HashSet<>();
File file = new File(filePath);
File[] files = file.listFiles();
for (File childFile : files) {
if (childFile.isDirectory()) {
if (isRecursion) {
className.addAll(getClassNameFromDir(childFile.getPath(), packageName + "." + childFile.getName(), isRecursion));
}
} else {
String fileName = childFile.getName();
if (fileName.endsWith(".class") && !fileName.contains("$")) {
className.add(packageName + "." + fileName.replace(".class", ""));
}
}
}
return className;
}
// /**
// * @param jarEntries
// * @param packageName
// * @param isRecursion
// * @return
// */
// private Set<String> getClassNameFromJar(Enumeration<JarEntry> jarEntries, String packageName, boolean isRecursion) {
// Set<String> classNames = new HashSet<String>();
//
// while (jarEntries.hasMoreElements()) {
// JarEntry jarEntry = jarEntries.nextElement();
// if (!jarEntry.isDirectory()) {
// /*
// * 这里是为了方便,先把"/" 转成 "." 再判断 ".class" 的做法可能会有bug
// * (FIXME: 先把"/" 转成 "." 再判断 ".class" 的做法可能会有bug)
// */
// String entryName = jarEntry.getName().replace("/", ".");
// if (entryName.endsWith(".class") && !entryName.contains("$") && entryName.startsWith(packageName)) {
// entryName = entryName.replace(".class", "");
// if (isRecursion) {
// classNames.add(entryName);
// } else if (!entryName.replace(packageName + ".", "").contains(".")) {
// classNames.add(entryName);
// }
// }
// }
// }
//
// return classNames;
// }
//
// /**
// * 从所有jar中搜索该包,并获取该包下所有类
// *
// * @param urls URL集合
// * @param packageName 包路径
// * @param isRecursion 是否遍历子包
// * @return 类的完整名称
// */
// private Set<String> getClassNameFromJars(URL[] urls, String packageName, boolean isRecursion) {
// Set<String> classNames = new HashSet<String>();
//
// for (int i = 0; i < urls.length; i++) {
// String classPath = urls[i].getPath();
//
// //不必搜索classes文件夹
// if (classPath.endsWith("classes/")) {
// continue;
// }
//
// JarFile jarFile = null;
// try {
// jarFile = new JarFile(classPath.substring(classPath.indexOf("/")));
// } catch (IOException e) {
// e.printStackTrace();
// }
//
// if (jarFile != null) {
// classNames.addAll(getClassNameFromJar(jarFile.entries(), packageName, isRecursion));
// }
// }
//
// return classNames;
// }
}
ProxyFactory.java
package com.lagou.edu.factory;
import com.lagou.edu.annotation.MyAutowired;
import com.lagou.edu.annotation.MyComponent;
import com.lagou.edu.utils.TransactionManager;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @author 应癫
*/
@MyComponent("proxyFactory")
public class ProxyFactory {
@MyAutowired
private TransactionManager transactionManager;
/**
* Jdk动态代理
*
* @param obj 委托对象
* @return 代理对象
*/
public Object getJdkProxy(Object obj) {
// 获取代理对象
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result;
try {
// 开启事务(关闭事务的自动提交)
transactionManager.beginTransaction();
result = method.invoke(obj, args);
// 提交事务
transactionManager.commit();
} catch (Exception e) {
e.printStackTrace();
// 回滚事务
transactionManager.rollback();
// 抛出异常便于上层servlet捕获
throw e;
}
return result;
}
});
}
/**
* 使用cglib动态代理生成代理对象
*
* @param obj 委托对象
* @return
*/
public Object getCglibProxy(Object obj) {
return Enhancer.create(obj.getClass(), new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
Object result;
try {
// 开启事务(关闭事务的自动提交)
transactionManager.beginTransaction();
result = method.invoke(obj, objects);
// 提交事务
transactionManager.commit();
} catch (Exception e) {
e.printStackTrace();
// 回滚事务
transactionManager.rollback();
// 抛出异常便于上层servlet捕获
throw e;
}
return result;
}
});
}
}