1、開發一個類加載器來加載基礎包名下的全部類,如使用了某註解的類,或者實現了某接口的類,又或者繼承了某父類的全部子類(編寫一個工具類,四個註解類)java
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.一、須要寫一個ClassUtil工具類,提供與類操做的相關方法,好比獲取類加載器,加載類,獲取指定包名下的全部類等等。apache
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<Class> * 1.根據包名將其轉換爲文件路徑 * 2讀取class或者jar包,獲取指定的類名去加載類 */ public static Set<Class<?>> getClassSet(String packageName){ Set<Class<?>> classSet = new HashSet<Class<?>>(); try { Enumeration<URL> 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<JarEntry> 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<Class<?>> 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<Class<?>> classSet, String className) { Class<?> cls = loadClass(className, false); classSet.add(cls); } public static void main(String[] args) { ClassUtil.getClassSet(ConfigHelper.getAppBasePackage()); } }
1.二、在控制器類上添加@Controller註解框架
1.三、方法上添加@Action註解ide
1.四、在服務類上添加@Service註解工具
1.五、在控制器中@Inject註解將服務類依賴注入進來url
1.六、咱們在配置文件中指定了整個應用的基礎包名(org.smart4j),經過ClassUtil工具加載的類都須要該基礎包名。因此咱們還須要提供一個ClassHelper助手類,讓他來獲取應用包名下的全部類、應用包名下的全部Service類、應用包名下的全部Controller類。( ps:咱們能夠將@Controller和@Service註解的類所產生的對象統一管理,能夠理解爲Smart框架所管理的全部Bean,因此還須要在ClassHelper類中增長一個獲取應用包名下全部Bean類的方法)。.net
1.七、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<?>> CLASS_SET; static{ String basePackage = ConfigHelper.getAppBasePackage(); //配置文件基礎包名 CLASS_SET = ClassUtil.getClassSet(basePackage); //加載全部類 } /** * 獲取應用包名下的全部類 * @return */ public static Set<Class<?>> getClassSet(){ return CLASS_SET; } /** * 獲取應用包名下的全部包含Service註解的類 * @return */ public static Set<Class<?>> getClassService(){ Set<Class<?>> classSet = new HashSet<Class<?>>(); for (Class<?> cls : CLASS_SET) { //遍歷全部的Class類對象 if( cls.isAnnotationPresent( Service.class ) ){ //若是包含Service註解 classSet.add(cls); } } return classSet; } /** * 獲取應用包名下的全部包含Controller註解的類 * @return */ public static Set<Class<?>> getClassController(){ Set<Class<?>> classSet = new HashSet<Class<?>>(); for (Class<?> cls : CLASS_SET) { //遍歷全部的Class類對象 if( cls.isAnnotationPresent( Controller.class ) ){ //若是包含Service註解 classSet.add(cls); } } return classSet; } /** * 獲取應用包名下的全部Bean類(包含:Controller、Service等) * @return */ public static Set<Class<?>> getBeanClassSet(){ Set<Class<?>> beanClassSet = new HashSet<Class<?>>(); beanClassSet.addAll( getClassService() ); beanClassSet.addAll( getClassController() ); return beanClassSet; } }
---------------------------------------summarize(總結):至此根據不一樣類型的註解來獲取指定的類對象( Class對象 )就大體編寫完畢,後續會常常用到ClassHelper助手類。獲得全部的Class對象之後,就要經過Class對象來實例化對象了,就是接下來的實現Bean容器。-----------------------------------------code