作者:田超凡
时间:2019年8月20日
因为整个项目是纯手写的,所以只需要依赖Apache的一些工具包,如collection、lang包,以及实现aop动态代理功能的cglib源包
作用:指定IOC扫描的基准包,一般配置为顶级包,下文IOC实现部分会递归扫描该基准包下的类
base_package=com.tcf.smart.framework.demo
作用:
(1).属性文件工具类,根据指定的属性文件名加载对应的属性文件
(2).根据Key获取属性值
package com.tcf.smart.framework.util;
import java.io.IOException;
import java.util.Properties;
/***
* TODO TCF 属性文件工具类,根据指定的属性文件名加载对应的属性文件
* TODO TCF 根据Key获取属性值
* @author 71485
*
*/
public class PropertiesUtil {
//TODO TCF 采用单例模式-饿汉模式
private static Properties properties=new Properties();
//TODO TCF 根据属性文件名加载属性文件
public static Properties loadProperties(String propertiesFileName)
{
try
{
properties.load(PropertiesUtil.class.getClassLoader().getResourceAsStream(propertiesFileName));
}
catch (IOException e)
{
e.printStackTrace();
}
return properties;
}
//TODO TCF 根据Key获取属性文件value
public static String getProperty(String key)
{
return properties.getProperty(key);
}
}
作用:
(1).类加载器工具类,获取类加载器、根据类名加载类、根据类名一次加载一个类、根据类名、包路径、包名一次加载所有子类、根据包名加载包及其子包下的所有类文件
package com.tcf.smart.framework.util;
import java.io.File;
import java.io.FileFilter;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.apache.commons.lang3.StringUtils;
import com.tcf.smart.framework.common.Const;
/***
* TODO TCF 类加载器工具类
* TODO TCF 获取类加载器、根据类名加载类、根据类名一次加载一个类、根据类名、包路径、包名一次加载所有子类、根据包名加载包及其子包下的所有类文件
* @author 71485
*
*/
public class ClassUtil {
//TODO TCF 获取类加载器
public static ClassLoader getClassLoader()
{
return Thread.currentThread().getContextClassLoader();
}
//TODO TCF 根据类名加载类
public static Class> loadClassByName(String className)
{
Class> cls=null;
try
{
cls=Class.forName(className,true,getClassLoader());
}
catch(Exception e)
{
e.printStackTrace();
}
return cls;
}
//TODO TCF 根据类名一次加载一个类
public static void addSingleClass(Set
{
try
{
Class> cls=loadClassByName(className);
classList.add(cls);
}
catch(Exception e)
{
e.printStackTrace();
}
}
//TODO TCF 根据包路径和包名递归加载所有类文件
public static void addClassBatch(Set
{
try
{
if(StringUtils.isNotEmpty(packagePath))
{
//TODO TCF 要扫描的基准目录
File dirFile=new File(packagePath);
if(dirFile!=null)
{
File[] files=dirFile.listFiles(new FileFilter() {
@Override
public boolean accept(File file)
{
return (file.isFile() && file.getName().endsWith(".class")) || file.isDirectory();
}
});
if(files!=null && files.length>0)
{
for(File file:files)
{
String fileName=file.getName();
if(StringUtils.isNotEmpty(fileName))
{
if(file.isFile())
{
//TODO TCF 扫描到的类文件加载到类加载器
String className=fileName.substring(0,fileName.lastIndexOf("."));
if(StringUtils.isNotEmpty(packageName))
{
className=packageName+"."+className;
}
addSingleClass(classList,className);
}
else
{
//TODO TCF 获取子包路径、子包名并递归加载
String subPackagePath=fileName;
if(StringUtils.isNotEmpty(packagePath))
{
subPackagePath=packagePath+"/"+subPackagePath;
}
String subPackageName=fileName;
if(StringUtils.isNotEmpty(packageName))
{
subPackageName=packageName+"."+subPackageName;
}
addClassBatch(classList, subPackagePath, subPackageName);
}
}
}
}
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
//TODO TCF 根据包名递归加载所有类文件
public static Set
{
Set
try
{
Enumeration
if(urls!=null)
{
while(urls.hasMoreElements())
{
URL url=urls.nextElement();
if(url!=null)
{
//TODO TCF URL协议类型
String protocol=url.getProtocol();
if(StringUtils.isNotEmpty(protocol))
{
if(protocol.equals(Const.URL_PROTOCOLS.FILE))
{
//TODO TCF 文件协议
String packagePath=url.getPath().replaceAll("%20"," ");
addClassBatch(classList, packagePath, packageName);
}
else if(protocol.equals(Const.URL_PROTOCOLS.JAR))
{
//TODO TCF JAR包协议
JarURLConnection jarURLConnection=(JarURLConnection)url.openConnection();
if(jarURLConnection!=null)
{
JarFile jarFile=jarURLConnection.getJarFile();
if(jarFile!=null)
{
Enumeration
if(entries!=null)
{
while(entries.hasMoreElements())
{
JarEntry jarEntry=entries.nextElement();
if(jarEntry!=null)
{
//TODO TCF jar文件名称
String entryName=jarEntry.getName();
if(StringUtils.isNotEmpty(entryName) && entryName.endsWith(".class"))
{
String className=entryName.substring(0,entryName.lastIndexOf(".")).replace("/",".");
addSingleClass(classList,className);
}
}
}
}
}
}
}
}
}
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
return classList;
}
}
作用:
(1).反射工具类,根据类型创建实例、基于反射机制执行对应方法、给对应属性注入属性值
package com.tcf.smart.framework.util;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/***
* TODO TCF 反射工具类
* TODO TCF 根据类型创建实例、基于反射机制执行对应方法、给对应属性注入属性值
* @author 71485
*
*/
public class ReflectUtil {
//TODO TCF 根据类型基于反射机制创建对应类型实例
public static Object newInstance(Class> cls)
{
Object instance=null;
try
{
instance=cls.newInstance();
}
catch(Exception e)
{
e.printStackTrace();
}
return instance;
}
//TODO TCF 基于反射机制给目标属性注入属性值
public static void setField(Object instance,Field field,Object fieldValue)
{
try
{
field.setAccessible(true);
field.set(instance,fieldValue);
}
catch(Exception e)
{
e.printStackTrace();
}
}
//TODO TCF 基于反射机制执行目标实例的方法
public static Object invokeMethod(Object instance,Method method,Object[] methodParams)
{
Object result=null;
try
{
result=method.invoke(instance,methodParams);
}
catch(Exception e)
{
e.printStackTrace();
}
return result;
}
}
作用:
(1).类加载器助手类,初始化加载基准包下的所有类存入临时容器,提供根据注解加载指定类的通用方法,提供根据继承关系加载父类下所有子类或接口所有实现类的方法
package com.tcf.smart.framework.helper;
import java.lang.annotation.Annotation;
import java.util.HashSet;
import java.util.Set;
import com.tcf.smart.framework.annotation.KidComponent;
import com.tcf.smart.framework.annotation.KidController;
import com.tcf.smart.framework.annotation.KidRepository;
import com.tcf.smart.framework.annotation.KidService;
import com.tcf.smart.framework.common.Const;
import com.tcf.smart.framework.util.ClassUtil;
import com.tcf.smart.framework.util.PropertiesUtil;
/**
* TODO TCF 类加载器助手类
* TODO TCF 初始化加载基准包下的所有类存入临时容器,提供根据注解加载指定类的通用方法,提供根据继承关系加载父类下所有子类或接口所有实现类的方法
* @author 71485
*
*/
public class ClassHelper {
public static Set
static
{
CLASS_LIST=ClassUtil.loadClassSetByPackageName(PropertiesUtil.loadProperties(Const.PROPERTIES_FILES.BASE_PROPERTIES).getProperty(Const.BASE_KEYS.BASE_PACKAGE));
}
//TODO TCF 根据注解加载对应类
public static Set
{
Set
if(CLASS_LIST!=null && CLASS_LIST.size()>0)
{
for(Class> cls:CLASS_LIST)
{
if(cls.isAnnotationPresent(annotation))
{
classList.add(cls);
}
}
}
return classList;
}
//TODO TCF 根据父类或接口加载其子类或实现类
public static Set
{
Set
if(CLASS_LIST!=null && CLASS_LIST.size()>0)
{
for(Class> cls:CLASS_LIST)
{
if(superClass.isAssignableFrom(cls) && !superClass.equals(cls))
{
classList.add(cls);
}
}
}
return classList;
}
//TODO TCF 加载预定义的注解标注类
public static Set
{
Set
classList.addAll(loadClassByAnnotation(KidComponent.class));
classList.addAll(loadClassByAnnotation(KidRepository.class));
classList.addAll(loadClassByAnnotation(KidService.class));
classList.addAll(loadClassByAnnotation(KidController.class));
return classList;
}
}
作用:
(1).自定义Bean组件及Bean实例映射管理工具类
(2).初始化加载Bean组件及其对应Bean实例,提供根据Bean类型获取Bean实例方法,提供存取元素方法
package com.tcf.smart.framework.helper;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/***
* TODO TCF 自定义Bean组件及Bean实例映射管理工具类
* TODO TCF 初始化加载Bean组件及其对应Bean实例,提供根据Bean类型获取Bean实例方法,提供存取元素方法
* @author 71485
*
*/
public class BeanHelper {
public static Map
static
{
Set
if(classList!=null && classList.size()>0)
{
for(Class> cls:classList)
{
try
{
Object instance=cls.newInstance();
BEAN_MAP.put(cls,instance);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
}
//TODO TCF 根据Bean类型获取Bean实例
public static Object getBeanByClass(Class> cls)
{
return BEAN_MAP.get(cls);
}
//TODO TCF 存入Bean组件和Bean实例映射元素
public static void putBeanMapping(Class> cls,Object instance)
{
BEAN_MAP.put(cls,instance);
}
}
作用:
(1).DI/IOC依赖注入助手类,加载基准包下的类并注入属性值,反射方法进行调用
package com.tcf.smart.framework.helper;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import com.tcf.smart.framework.annotation.Aspect;
import com.tcf.smart.framework.annotation.KidController;
import com.tcf.smart.framework.annotation.KidInject;
import com.tcf.smart.framework.demo.TestDemoFirst;
import com.tcf.smart.framework.demo.TestDemoSecond;
import com.tcf.smart.framework.demo.TestDemoThird;
import com.tcf.smart.framework.util.ReflectUtil;
/***
* TODO TCF DI/IOC依赖注入助手类,加载基准包下的类并注入属性值,反射方法进行调用
* @author 71485
*
*/
public class IocHelper {
static
{
//TODO TCF simpleClassName => fieldName:fieldValue
Map
//TODO TCF 需要注入的属性名:属性值
Map
paramMap.put("name","张三");
fieldMap.put(TestDemoFirst.class.getSimpleName(),paramMap);
paramMap=new HashMap
paramMap.put("age",18);
fieldMap.put(TestDemoSecond.class.getSimpleName(),paramMap);
paramMap=new HashMap
paramMap.put("first",new TestDemoFirst());
fieldMap.put(TestDemoThird.class.getSimpleName(),paramMap);
//TODO TCF 启动容器,实现DI/IOC依赖注入
init(fieldMap);
}
//TODO TCF DI/IOC容器启动
public static void init(Map
{
//TODO TCF 获取Bean组件和实例映射Map
Map
if(beanMap!=null)
{
for(Map.Entry
{
//TODO TCF 目标类型
Class> targetClass=entry.getKey();
//TODO TCF 过滤AOP已经加载的代理类
if(targetClass.isAnnotationPresent(Aspect.class))
{
continue;
}
//TODO TCF 目标类型实例
Object instance=entry.getValue();
//TODO TCF 目标类型下面定义的所有属性
Field[] fields=targetClass.getDeclaredFields();
if(fields!=null && fields.length>0)
{
for(Field field:fields)
{
if(field.isAnnotationPresent(KidInject.class))
{
//TODO TCF 参数注入使用KidInject注解标注的属性
for(Map.Entry
{
//TODO TCF 属性所在类型名称
String className=fieldEntry.getKey();
//TODO TCF 属性KEY-VALUE键值对
Map
if(StringUtils.isNotEmpty(className))
{
if(className.equals(targetClass.getSimpleName()))
{
//TODO TCF 注入属性值
for(Map.Entry
{
//TODO TCF 属性值
Object fieldValue=destEntry.getValue();
//TODO TCF 注入属性值
ReflectUtil.setField(instance, field, fieldValue);
}
}
}
}
}
}
}
//TODO TCF 只执行AOP代理的控制器方法
//TODO TCF 实际可以去掉该条件或换成其他条件,满足条件的目标类中的方法会被执行
if(targetClass.isAnnotationPresent(KidController.class))
{
//TODO TCF 反射执行目标方法
Method[] methods=targetClass.getDeclaredMethods();
if(methods!=null && methods.length>0)
{
for(Method method:methods)
{
//TODO TCF 方法参数
Object[] methodParams=null;
//TODO TCF ...方法入参补全
ReflectUtil.invokeMethod(instance, method, methodParams);
}
}
}
}
}
}
}
作用:自定义项目需要使用的注解及其功能
@KidComponent 注册普通组件 => @Component
@KidRepository 注册持久层组件 => @Repository
@KidService 注册业务层组件 => @Service
@KidController 注册控制器组件 => @Controller
@KidInject 显式指定需要注入值的属性 => @Inject
@Aspect 定义切面类 => @Aspect
package com.tcf.smart.framework.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface KidComponent {
}
package com.tcf.smart.framework.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface KidRepository {
}
package com.tcf.smart.framework.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface KidService {
}
package com.tcf.smart.framework.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface KidInject {
}
package com.tcf.smart.framework.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface KidController {
}
package com.tcf.smart.framework.annotation;
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Aspect {
//TODO TCF 获取切面注解值
Class extends Annotation> value();
}
package com.tcf.smart.framework.common;
/***
* TODO TCF 常量类
* @author 71485
*
*/
public class Const {
//TODO TCF 属性配置文件名
public static class PROPERTIES_FILES
{
//TODO TCF IOC和AOP配置文件
public static final String BASE_PROPERTIES="base.properties";
}
//TODO TCF URL协议类型
public static class URL_PROTOCOLS
{
//TODO TCF file文件协议
public static final String FILE="file";
//TODO TCF jar文件协议
public static final String JAR="jar";
}
//TODO TCF 属性文件key
public static class BASE_KEYS
{
//TODO TCF 基准包目录
public static final String BASE_PACKAGE="base_package";
}
}
作用:
(1).代理接口,定义封装的切面方法织入各类增强,调用代理实例的执行链依次执行代理方法
package com.tcf.smart.framework.aop;
/**
* TODO TCF 代理接口,定义封装的切面方法织入各类增强,调用代理实例的执行链依次执行代理方法
* @author 71485
*
*/
public interface Proxy {
//TODO TCF 执行增强方法
public Object doProxy(ProxyChain proxyChain);
}
作用:
(1).代理实例执行链,跟踪代理实例执行顺序
package com.tcf.smart.framework.aop;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import net.sf.cglib.proxy.MethodProxy;
/***
* TODO TCF 代理实例执行链,跟踪代理实例执行顺序
* @author 71485
*
*/
public class ProxyChain {
//TODO TCF 代理目标类型
private Class> targetClass;
//TODO TCF 代理目标实例
private Object targetInsatnce;
//TODO TCF 代理目标方法
private Method targetMethod;
//TODO TCF 代理方法
private MethodProxy methodProxy;
//TODO TCF 方法参数
private Object[] methodParams;
//TODO TCF 存放代理实例的集合
private List
//TODO TCF 记录执行链执行索引
private static Integer proxyExecuteIndex=0;
//TODO TCF 获取代理目标类型、目标实例、目标方法、方法参数
public Class> getTargetClass() {
return targetClass;
}
public Object getTargetInsatnce() {
return targetInsatnce;
}
public Method getTargetMethod() {
return targetMethod;
}
public Object[] getMethodParams() {
return methodParams;
}
public List
return proxyList;
}
//TODO TCF 构造注入代理信息
public ProxyChain(
Class> targetClass,
Object targetInstance,
Method targetMethod,
MethodProxy methodProxy,
Object[] methodParams,
List
)
{
this.targetClass=targetClass;
this.targetInsatnce=targetInstance;
this.targetMethod=targetMethod;
this.methodProxy=methodProxy;
this.methodParams=methodParams;
this.proxyList=proxyList;
}
//TODO TCF 代理执行链启动
public Object doProxyChain()
{
Object result=null;
if(proxyExecuteIndex
result=proxyList.get(proxyExecuteIndex++).doProxy(this);
}
else
{
try
{
result=methodProxy.invokeSuper(targetInsatnce,methodParams);
}
catch (Throwable e)
{
e.printStackTrace();
}
}
return result;
}
}
作用:
(1).代理模式工厂类,基于cglib创建多个代理实例并执行对应代理方法
package com.tcf.smart.framework.aop;
import java.lang.reflect.Method;
import java.util.List;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
* TODO TCF 代理模式工厂类,基于cglib创建多个代理实例并执行对应代理方法
* @author 71485
*
*/
public class ProxyManager {
@SuppressWarnings("unchecked")
public static
{
return (T) Enhancer.create(targetClass,new MethodInterceptor() {
@Override
public Object intercept(Object targetInstance,
Method targetMethod,
Object[] methodParams,
MethodProxy methodProxy) throws Throwable
{
return new ProxyChain(targetClass, targetInstance, targetMethod, methodProxy, methodParams, proxyList).doProxyChain();
}
});
}
}
作用:
(1).切面基类,定义通用的各类增强处理方法,其他切面类直接继承该类重写对应增强处理即可
package com.tcf.smart.framework.aop;
/***
* TODO TCF 切面基类,定义通用的各类增强处理方法,其他切面类直接继承该类重写对应增强处理即可
* @author 71485
*
*/
public abstract class ProxyAspect implements Proxy{
@Override
public Object doProxy(ProxyChain proxyChain)
{
Object result=null;
//TODO TCF 织入增强处理
try
{
before();
result=proxyChain.doProxyChain();
after();
}
catch(Exception e)
{
e.printStackTrace();
}
return result;
}
//TODO TCF 自定义各类增强处理
//TODO TCF 前置增强
public void before()
{
System.out.println("====前置增强 before====");
}
//TODO TCF 后置增强
public void after()
{
System.out.println("====后置增强 afterReturning====");
}
}
作用:
(1).AOP切面助手类
(2).初始化加载所有基准包下的目标类及其对应的代理类,批量创建每个目标类的多个代理实例并调用对应的代理方法执行(织入增强处理效果)
package com.tcf.smart.framework.helper;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.tcf.smart.framework.annotation.Aspect;
import com.tcf.smart.framework.aop.Proxy;
import com.tcf.smart.framework.aop.ProxyAspect;
import com.tcf.smart.framework.aop.ProxyManager;
/***
* TODO TCF AOP切面助手类
* TODO TCF 初始化加载所有基准包下的目标类及其对应的代理类,批量创建每个目标类的多个代理实例并调用对应的代理方法执行(织入增强处理效果)
* @author 71485
*
*/
public class AopHelper {
static
{
//TODO TCF 加载基准包下的所有代理类
//TODO TCF 代理类:代理的所有目标类
Map
//TODO TCF 目标类:目标类的所有代理类
Map
if(targetMap!=null)
{
for(Map.Entry
{
//TODO TCF 目标类
Class> targetClass=entry.getKey();
//TODO TCF 目标类的所有代理类
List
//TODO TCF 批量创建cglib代理实例
Object result=ProxyManager.newProxyInstance(targetClass, proxyList);
//TODO TCF 存入Bean组件和Bean实例映射(目标类的实例使用创建的代理实例);
BeanHelper.putBeanMapping(targetClass,result);
}
}
}
//TODO TCF 读取切面子类(目标类)
public static Set
{
Set
Class extends Annotation> annotation=aspect.value();
if(annotation!=null && !annotation.equals(Aspect.class))
{
classList.addAll(ClassHelper.loadClassByAnnotation(annotation));
}
return classList;
}
//TODO TCF 读取代理类:代理的所有目标类
public static Map
{
Map
//TODO TCF 代理的所有目标类
Set
if(classList!=null)
{
for(Class> proxyClass:classList)
{
if(proxyClass.isAnnotationPresent(Aspect.class))
{
Aspect aspect=proxyClass.getAnnotation(Aspect.class);
Set
proxyMap.put(proxyClass,targetClassList);
}
}
}
return proxyMap;
}
//TODO TCF 读取目标类,目标的所有代理类
public static Map
{
Map
if(proxyMap!=null)
{
for(Map.Entry
{
//TODO TCF 代理类
Class> proxyClass=entry.getKey();
//TODO TCF 代理的所有目标类
Set
for(Class> targetClass:targetClassList)
{
try
{
Proxy proxy=(Proxy)proxyClass.newInstance();
if(targetMap.containsKey(targetClass))
{
targetMap.get(targetClass).add(proxy);
}
else
{
List
proxyList.add(proxy);
targetMap.put(targetClass,proxyList);
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
}
return targetMap;
}
}