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