博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
从0开始写JavaWeb框架系列(2)从0开始写SamrtFrameWork:开发一个类加载器
阅读量:6876 次
发布时间:2019-06-26

本文共 7746 字,大约阅读时间需要 25 分钟。

hot3.png

一、开发一个类加载器来加载基础包名下的所有类,如使用了某注解的类,或者实现了某接口的类,又或者继承了某父类的所有子类(编写一个工具类,四个注解类)

package org.smart4j.framework.annotation;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;//控制器类上带有@Controller注解的类@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface Controller {}
package org.smart4j.framework.annotation;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * 服务层 * @author Admin * */@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface Service {}
package org.smart4j.framework.annotation;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * 依赖注入 * @author Admin * */@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface Inject {}
package org.smart4j.framework.annotation;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * 控制器类上带有Action注解的方法( @Action("get:/customerEdit")   ) * @author Admin * */@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface Action {	/**	 * 请求类型与路径	 */	String value();}

 

  1.1、需要写一个ClassUtil工具类,提供与类操作的相关方法,比如获取类加载器,加载类,获取指定包名下的所有类等等。

            

package org.smart4j.framework.util;import java.io.File;import java.io.FileFilter;import java.io.IOException;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 org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.smart4j.framework.helper.ConfigHelper;/** * 类操作工具类 * @author TS * */public final class ClassUtil {	private static final Logger LOGGER = LoggerFactory.getLogger(ClassUtil.class);	/**	 * 获取当前线程中的类加载器	 * @return ClassLoader对象	 */	public static ClassLoader getClassLoader(){		return Thread.currentThread().getContextClassLoader();	}	/**	 * 加载类	 * @param className 类的全限定名	 * @param isInitialied 是否初始化的标志(是否执行类的静态代码块)TODO	 * @return	 */	public static Class
loadClass(String className,boolean isInitialied){ Class
cls; try { cls = Class.forName(className, isInitialied, getClassLoader()); } catch (ClassNotFoundException e) { LOGGER.error("加载类初始化错误"); throw new RuntimeException(e); } return cls; } /** * 加载类 * @param className 类的全限定名 * @return */ public static Class
loadClass(String className){ Class
cls; try { cls = Class.forName(className); } catch (ClassNotFoundException e) { LOGGER.error("加载类初始化错误"); throw new RuntimeException(e); } return cls; } /** * 获取指定包名下的所有类 * @param packageName 包名 * @return Set
* 1.根据包名将其转换为文件路径 * 2读取class或者jar包,获取指定的类名去加载类 */ public static Set
> getClassSet(String packageName){ Set
> classSet = new HashSet
>(); try { Enumeration
urls = getClassLoader().getResources(packageName.replace(".", "/")); if( urls.hasMoreElements() ){ URL url = urls.nextElement(); if(url != null ){ String protocol = url.getProtocol(); //协议名称 if( protocol.equals("file") ){ String packagePath = url.getPath().replace("%20", " "); //加载类 addClass(classSet,packagePath,packageName); }else if( protocol.equals("jar") ){ JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection(); if( jarURLConnection != null ){ JarFile jarFile = jarURLConnection.getJarFile(); if( jarFile != null ){ Enumeration
jarEntries = jarFile.entries(); while ( jarEntries.hasMoreElements() ) { JarEntry jarEntry = jarEntries.nextElement(); String jarEntryName = jarEntry.getName(); if( jarEntryName.endsWith(".class") ){ String className = jarEntryName.substring(0,jarEntryName.lastIndexOf(".")).replaceAll("/", "."); doAddClass(classSet,className); } } } } } } } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return classSet; } private static void addClass(Set
> classSet, String packagePath, String packageName) { File[] files = new File(packagePath).listFiles(new FileFilter() { @Override public boolean accept(File file) { return ( file.isFile() && file.getName().endsWith(".class") ) || file.isDirectory(); } }); for (File file : files) { String fileName = file.getName(); System.out.println(fileName); if( file.isFile() ){ String className = fileName.substring( 0,fileName.lastIndexOf(".") ); if( StringUtils.isNotEmpty(packageName) ){ className = packageName + "." + className; } doAddClass(classSet, className); } else { String subPackagePath = fileName; if( StringUtils.isNotEmpty(packagePath) ){ subPackagePath = packagePath + "/" + subPackagePath; } String subPackageName = fileName; if( StringUtils.isNotEmpty(subPackageName) ){ subPackageName = packageName + "." + subPackageName; } addClass(classSet, subPackagePath, subPackageName); } } } private static void doAddClass(Set
> classSet, String className) { Class
cls = loadClass(className, false); classSet.add(cls); } public static void main(String[] args) { ClassUtil.getClassSet(ConfigHelper.getAppBasePackage()); }}

    1.2、在控制器类上添加@Controller注解

    1.3、方法上添加@Action注解

    1.4、在服务类上添加@Service注解

    1.5、在控制器中@Inject注解将服务类依赖注入进来

    1.6、我们在配置文件中指定了整个应用的基础包名(org.smart4j),通过ClassUtil工具加载的类都需要该基础包名。所以我们还需要提供一个ClassHelper助手类,让他来获取应用包名下的所有类、应用包名下的所有Service类、应用包名下的所有Controller类。( ps:我们可以将@Controller和@Service注解的类所产生的对象统一管理,可以理解为Smart框架所管理的所有Bean,所以还需要在ClassHelper类中增加一个获取应用包名下所有Bean类的方法)。

    1.7、ClassHelper就完美封装了ClassUtil工具类,并提供了一系列助手方法,通过这些方法可以直接获得我们想要的Class类对象的集合.开发者就可以ClassUtil 这个工具类了。

            

package org.smart4j.framework.helper;import java.util.HashSet;import java.util.Set;import org.smart4j.framework.annotation.Controller;import org.smart4j.framework.annotation.Service;import org.smart4j.framework.util.ClassUtil;/** * 类操作助手类 * @author TS * */public final class ClassHelper {	//获取应用下的所有Class类对象	//获取@Controller注解所有的Class类对象	//获取@Service注解所有的Class类对象		/**	 * 定义集合类( 存放所加载的类 )	 */	private static final Set
> CLASS_SET; static{ String basePackage = ConfigHelper.getAppBasePackage(); //配置文件基础包名 CLASS_SET = ClassUtil.getClassSet(basePackage); //加载所有类 } /** * 获取应用包名下的所有类 * @return */ public static Set
> getClassSet(){ return CLASS_SET; } /** * 获取应用包名下的所有包含Service注解的类 * @return */ public static Set
> getClassService(){ Set
> classSet = new HashSet
>(); for (Class
cls : CLASS_SET) { //遍历所有的Class类对象 if( cls.isAnnotationPresent( Service.class ) ){ //如果包含Service注解 classSet.add(cls); } } return classSet; } /** * 获取应用包名下的所有包含Controller注解的类 * @return */ public static Set
> getClassController(){ Set
> classSet = new HashSet
>(); for (Class
cls : CLASS_SET) { //遍历所有的Class类对象 if( cls.isAnnotationPresent( Controller.class ) ){ //如果包含Service注解 classSet.add(cls); } } return classSet; } /** * 获取应用包名下的所有Bean类(包含:Controller、Service等) * @return */ public static Set
> getBeanClassSet(){ Set
> beanClassSet = new HashSet
>(); beanClassSet.addAll( getClassService() ); beanClassSet.addAll( getClassController() ); return beanClassSet; } }

---------------------------------------summarize(总结):至此根据不同类型的注解来获取指定的类对象( Class对象 )就大致编写完毕,后续会经常用到ClassHelper助手类。得到所有的Class对象以后,就要通过Class对象来实例化对象了,就是接下来的实现Bean容器。-----------------------------------------

转载于:https://my.oschina.net/tianshuo/blog/682260

你可能感兴趣的文章
我的友情链接
查看>>
我的友情链接
查看>>
我的友情链接
查看>>
UIWebView加载html网页时使用缓存和清空缓存
查看>>
我的友情链接
查看>>
设计模式学习笔记(六)之策略模式(Strategy)
查看>>
python运行spark脚本程序
查看>>
我的友情链接
查看>>
通过libvirt使用ceph块设备
查看>>
优秀交互设计师成长指南
查看>>
SDN网络系统之MiniNet的安装与使用
查看>>
java的Iterator和listIterator的区别
查看>>
服务器虚拟化的好处
查看>>
AxureRP7.0基础教程系列 部件详解 表格Tabel
查看>>
ORACLE之sql语句优化
查看>>
一台机器同时启动多个tomcat
查看>>
Java中的多线程
查看>>
Zookeeper不适合注册中心的原因
查看>>
内核是什么
查看>>
标签的语义
查看>>