上一节介绍了一些spring基本知识 和 实现ioc的思路 ,下面按照整个思路一步步来完成咱们自己的ioc framework
在instance你annotation的class和inject属性的时候,首先你要扫描的你配置的package以及package子包下的所有class是否标注有annotation(如:@Repository,@Service,@Controller)
这里有几个问题?
①怎么定义java annotation?
这里我要模仿spring定义四个java annotation 用于你dao层、service层 、action层用于标注你各层的bean 以及用于inject属性的java annotation
java annotation Dao.java
package com.ajunframework.beans.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 应用于dao层实例化
* @author ajun
* @http://blog.youkuaiyun.com/ajun_studio
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Dao {
public String value() default "";
}
java annotation Service.java
package com.ajunframework.beans.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.ajunframework.beans.constant.BeanScop;
/**
* 实例化service
* @author ajun
* @http://blog.youkuaiyun.com/ajun_studio
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Service {
public String value() default “”;
}
java annotation Action.java
package com.ajunframework.beans.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 应用在action 实例化
* @author ajun
* @http://blog.youkuaiyun.com/ajun_studio
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Action {
public String value() default "";
}
java annotation Property.java
package com.ajunframework.beans.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 进行依赖注入
* @author ajun
* @http://blog.youkuaiyun.com/ajun_studio
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Property {
public String value() default "";
}
②怎么扫描?
这里提供一个用于扫描package以及package子包下的所有class PackageUtils.java
package com.ajunframework.beans.utils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
/**
* @author ajun
* @http://blog.youkuaiyun.com/ajun_studio
*/
public class PackageUtils {
/**
* 扫描给定包及子包内的所有类
*
* @param packageName
* 给定的包名
* @return The classes
* @throws ClassNotFoundException
* @throws IOException
*/
@SuppressWarnings("unchecked")
public static Class[] getClasses(String packageName)
throws ClassNotFoundException, IOException {
Class cla = PackageUtils.class;
String path = packageName.replace('.', '/');
Enumeration<URL> resources = cla.getClassLoader().getResources(path);
List<File> dirs = new ArrayList<File>();
while (resources.hasMoreElements()) {
URL resource = resources.nextElement();
dirs.add(new File(resource.getFile()));
}
ArrayList<Class> classes = new ArrayList<Class>();
for (File directory : dirs) {
classes.addAll(findClasses(directory, packageName));
}
return classes.toArray(new Class[classes.size()]);
}
/**
* 找到制定包内的所有class文件
*
* @param directory
* 目录名称
* @param packageName
* 包名称
* @return The classes
* @throws ClassNotFoundException
*/
@SuppressWarnings("unchecked")
private static List<Class> findClasses(File directory, String packageName)
throws ClassNotFoundException {
List<Class> classes = new ArrayList<Class>();
if (!directory.exists()) {
return classes;
}
File[] files = directory.listFiles();
for (File file : files) {
if (file.isDirectory()) {
classes.addAll(findClasses(file,
packageName + "." + file.getName()));
} else if (file.getName().endsWith(".class")) {
classes.add(Class.forName(packageName
+ '.'
+ file.getName().substring(0,
file.getName().length() - 6)));
}
}
return classes;
}
/**
* @throws IOException
* @throws ClassNotFoundException
*
*/
// public static void main(String[] args) throws Exception {
// Class[] clas = PackageUtils.getClassess("com.ajunframework.utils");
// for (Class cla : clas) {
// System.out.println(cla.getName());
// }
// }
}
扫描的路径怎么传入呢 ?这里可以定义一个properties文件 用于定义一些常量
constant.properties
scan-package=com.ajun.test #这里是你要的package的路径
下面可以提供一个读取constant.properties文件 ,供外包调用返回class[]数组的工具类 ScanClass.java
package com.ajunframework.beans.scan;
import java.io.IOException;
import com.ajunframework.beans.utils.PackageUtils;
import com.ajunframework.beans.utils.PubConstant;
/**
* 获得某个包或者子包下的所有class
* @author ajun
* @http://blog.youkuaiyun.com/ajun_studio
*/
public class ScanClass {
/**
* 获得某个包或者子包下的所有class
* @return
*/
public static Class<?>[] getScanPackageClasses(){
String packageLink = PubConstant.getValue("scan-package");
Class<?>[] clas=null;
try {
clas = PackageUtils.getClasses(packageLink);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return clas;
}
}
到目前为止,可以扫描指定package以及子package下的所有class了,下一节我们会介绍怎么收集和整理这些扫描到得class的信息