主要模拟的是Repository
、Controller
、Service和
Autowired四个注解,利用反射机制创建容器和实例对象
其中Autowired注解中扫描容器中实例属性
可以完成实例的向上转型
1、自定义注解
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 Autowired {
}
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 Controller {
String value() default "";
}
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 Repository {
String value() default "";
}
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 Service {
String value() default "";
}
2、创建工厂
import java.util.HashMap;
import java.util.Map;
public class BeanFactory {
private static Map<String,Object> beanMap;
static {
beanMap = new HashMap<>();
}
public static Map<String, Object> getBeanMap() {
return beanMap;
}
public static void setBeanMap(Map<String, Object> beanMap) {
BeanFactory.beanMap = beanMap;
}
/*
根据唯一标识获取对应的实例
*/
public static Object getBean(String id){
return beanMap.get(id);
}
}
3、开启包扫描
import com.ujs.ioc.annotation.Autowired;
import com.ujs.ioc.annotation.Controller;
import com.ujs.ioc.annotation.Repository;
import com.ujs.ioc.annotation.Service;
import com.ujs.ioc.factory.BeanFactory;
import java.io.File;
import java.io.FileFilter;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/*
模拟spring基于注解进行解耦
*/
public class ComponentScan {
private static List<String> classNameList = new ArrayList<>();
//在Autowired注解注入的时候,存放类本身以及其接口和父类,进行类型匹配
private static ArrayList<Class> parentArrayList = new ArrayList<>();
public static void componentScan(String basePackage){
//将传递过来的包结构.变成/
basePackage = basePackage.replace(".","/");
//获取系统的绝对路径
String path = ClassLoader.getSystemResource("").getPath()+basePackage;
//创建文件对象
File file = new File(path);
//过滤出符合条件的文件
if (file.exists())
isFile(file);
//遍历全类名集合
for (String className : classNameList) {
try {
//创建字节码对象
Class aClass = Class.forName(className);
//通过反射获取类上的注解
Controller controller = (Controller)aClass.getAnnotation(Controller.class);
Service service = (Service)aClass.getAnnotation(Service.class);
Repository repository = (Repository)aClass.getAnnotation(Repository.class);
//判断注解是否存在
if (controller != null || service != null || repository != null){
//创建当前类的实例
Object instance = aClass.newInstance();
String value = null;
String id = null;
//获取当前类的标识
if (controller != null){
value = controller.value();
}else if (service != null){
value = service.value();
}else if (repository != null){
value = repository.value();
}
if (value != null && !value.equals("")){
id = value; //自定义唯一标识
}else {
//如果没有自定义唯一标识,那么唯一标识就是类名首字母小写
id = aClass.getSimpleName().split("")[0].toLowerCase()+aClass.getSimpleName().substring(1);
}
//将唯一标识和实例存储到容器中
BeanFactory.getBeanMap().put(id,instance);
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
//遍历全类名集合,完成实例的注入
Set<Map.Entry<String, Object>> entries = BeanFactory.getBeanMap().entrySet();
for (Map.Entry<String, Object> entry : entries) {
Object value = entry.getValue();//获取类
Class<?> aClass = value.getClass(); //获取当前类的字节码对象
//遍历类中的属性,判断属性上是否存在Autowired注解
for (Field declaredField : aClass.getDeclaredFields()) {
//这个属性中存在注解
if(declaredField.getAnnotation(Autowired.class)!=null){
//注入属性值,找到容器中存放的实例
Object newInstance = null; //需要注入的实例
//遍历容器中的实例对象,找到需要注入的实例对象
for (Map.Entry<String, Object> objectEntry : entries) {
//获取容器中的类的接口以及父类,判断是否与该属性值类型相同
parentArrayList.clear(); //清空
Class<?> targetClass = objectEntry.getValue().getClass();
parentArrayList.add(targetClass);
//查询当前类的所有接口
getAllInterface(targetClass);
//获取当前类的所有父类
getAllSuperClass(targetClass);
//只要该实例中存在一个父接口或者父类或者本身的类型匹配,就赋值
for (Class aClass1 : parentArrayList) {
//类型匹配
if(aClass1 == declaredField.getType()){
newInstance = objectEntry.getValue();
break;
}
}
if(newInstance!=null)
break;
}
if(newInstance==null){
System.out.println("Autowired注解没有匹配到对应的实例");
return;
}
//打破封装
declaredField.setAccessible(true);
//给属性赋值
try {
declaredField.set(value,newInstance);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
}
}
/**
* 获取一个字节码对象的所有父接口
*/
public static void getAllInterface(Class targetClass){
Class<?>[] interfaces = targetClass.getInterfaces();
for (Class<?> anInterface : interfaces) {
parentArrayList.add(anInterface);
getAllInterface(anInterface);
}
}
/**
* 获取一个字节码对象的所有父接口
*/
public static void getAllSuperClass(Class targetClass){
Class superclass = targetClass.getSuperclass();
if (!superclass.getName().equals("java.lang.Object")){
System.out.println(superclass);
parentArrayList.add(superclass);
getAllSuperClass(superclass);
}
}
public static void isFile(File file){
//过滤符合要求的文件
File[] files = file.listFiles(new FileFilter() {
/**
* 文件一定是以.class结尾的
* @return
*/
@Override
public boolean accept(File file) {
//判断是不是文件夹
if (file.isDirectory()){
isFile(file);//递归调用该方法,再次过滤文件夹中的文件
}else {
return file.getPath().endsWith(".class");
}
return false;
}
});
//将所有的路径切割成全类名
for (File fileClass : files) {
String path = fileClass.getPath();
//去掉系统路径
path = path.replace(ClassLoader.getSystemResource("").getPath().substring(1).replace("/","\\"),"");
path = path.replace("\\",".");
path = path.replace(".class","");
classNameList.add(path);
}
}
}
4、测试
import com.ujs.ioc.ComponentScan;
import com.ujs.ioc.account.servlet.AccountServlet;
import com.ujs.ioc.factory.BeanFactory;
import java.util.Map;
public class SpringTest03 {
public static void main(String[] args) {
//开启扫描包,输入包结构
ComponentScan.componentScan("com.ujs");
Map<String, Object> beanMap = BeanFactory.getBeanMap();
for (Map.Entry<String, Object> objectEntry : beanMap.entrySet()) {
System.out.println(objectEntry.getKey() +"===> "+objectEntry.getValue());
}
Object servlet1 = BeanFactory.getBean("servlet");
Object servlet2 = BeanFactory.getBean("servlet");
System.out.println(servlet1 == servlet2);
//从核心容器对象中取到表现层实例
AccountServlet accountServlet = (AccountServlet)BeanFactory.getBean("servlet");
if(accountServlet!=null)
accountServlet.saveAccount();
else{
System.out.println("实例获取失败");
}
}
}