当前位置: 首页 > 后端技术 > Java

Java培训如何使用反射制作一个简单的SpringIOC容器

时间:2023-04-01 23:49:28 Java

前言在学习了Spring之后,我对其工作原理产生了浓厚的兴趣。最近通过看视频了解了一些SpringIOC容器的工作原理,边打磨边制作了一个非常简单的SpringIOC容器,实现了他的。XML文件组装、java代码组装和自动组装功能,以下思路和代码一、仿XML形式的组装思路一、思路在使用XML组装bean时,Spring会解析applicationContext.xml文件,将各种类型的bean注入到IOC中容器,容器中的bean可以无数次重复调用,无需多次重复新建对象,大大提高了系统效率。为了模仿IOC,我们使用Map集合来存放需要的bean,并新建一个conf.properties文件来存放信息,存放com.wql.dao.userDao=com.wql.daoImpl.userDaoImpl_java训练等数据信息在获取bean之前解析conf.properties文件中的信息,使用反射技术将conf.properties文件中的内容以Class.forName的形式解析成Class对象并放入collectionmap中,这样每次获取对象获取后,会从map中获取,无需new2。具体代码实现conf.properties:com.wql.dao.userDao=com.wql.daoImpl.userDaoImplcom.wql.service.userService=com.wql.serviceImpl.userServiceImplMyApplicationContext类代码实现:packagecom.wql.application;importjava.io.InputStream;importjava.util.HashMap;importjava.util.Map;importjava.util.Properties;importjava.util.Set;publicclassMyApplicationContext{//模拟IOC容器privateMapmap=newHashMap<>();privateStringResourcePath;privateStringfilepath;publicMyApplicationContext(){}publicMyApplicationContext(StringresourcePath){ResourcePath=resourcePath;}//获取未知类型的对象(通过map集合)publicTgetBean(Classclazz){return(T)map.get(clazz);}//通过properties中存储的键值对获取Class对象,注入到map集合中Propertiesproperties=newProperties();properties.load(stream);//获取内容Setkeys=properties.keySet();for(Objectkey:keys){//Class:instancemap.put(Class.forName(key.toString()),Class.forName(properties.getProperty(key.toString())).newInstance());}}catch(Exceptione){e.printStackTrace();}}}我们测试code:visible对象成功获取,但是这种拼装的方式好像落伍了。接下来我们通过@Bean实现注入2.通过注解注入1.思路是先获取项目路径,然后通过字符串拦截获取接口实现类类的全路径,检查类中是否包含@Bean注解通过反射技术,有map2就加上。代码实现@Bean:packagecom.wql.Annotation;importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public@interfaceBean{}MyApplicationContext类代码实现://通过注解组装beanpublicvoidinitAnnotationSpringIOC(){filepath=MyApplicationContext.class.getClassLoader().getResource("").getFile();//获取工程路径后System.out.println(filepath);loadOne(newFile(filepath));}privatevoidloadOne(Filefileparent){if(fileparent.isDirectory()){//获取子文件File[]files=fileparent.listFiles();if(files.length==0||files==null){return;}else{//它下面的文件夹不为空for(Filefile:files){if(file.isDirectory()){loadOne(file);}else{try{Stringoldpath=file.getAbsolutePath().substring(filepath.length()-1、file.getAbsolutePath().length());if(oldpath.contains(".class")){Stringnewpath=oldpath.replaceAll("\\",".").replace(".class","");ClassaClass=Class.forName(newpath);//模拟组装beanif(!aClass.isInterface()){if(aClass.getAnnotation(Bean.class)!=null){//证明该类包含Bean注解,将其添加到mapmap.put(aClass.getInterfaces()[0],aClass.newInstance());}}}}catch(Exceptione){e.printStackTrace();}}}}}}在代码中,我们通过MyApplicationContext.class逐步接近。getClassLoader().getResource("").getFile();获取项目路径,所以我们有办法获取.class文件_java培训机构项目路径:/D:/IdeaJava/untitled1/out/production/MySpringIOCProject/usefile.getAbsolutePath().substring(filepath.length()-1、file.getAbsolutePath().length());我们成功拦截了.class文件和其他文件com\wql\Annotation\Bean.classcom\wql\Annotation\MyAutowired.classcom\wql\application\ApplicationContext.classcom\wql\application\MyApplicationContext.classcom\wql\dao\的路径userDao.classcom\wql\daoImpl\userDaoImpl.classcom\wql\entity\User.classcom\wql\service\userService.classcom\wql\serviceImpl\userServiceImpl.classcom\wql\test\test.classconf.propertiesMETA-INF\MySpringIOCProject。kotlin_module然后使用contains方法过滤掉后缀为.class的文件,将其路径改为/,替换为.class字符并删除,我们得到:com.wql.Annotation.Beancom.wql.Annotation.MyAutowiredcom。wql.application.ApplicationContextcom.wql.application.MyApplicationContextcom.wql.dao.userDaocom.wql.daoImpl.userDaoImplcom.wql.entity.Usercom.wql.service.userServicecom.wql.serviceImpl.userServiceImplcom.wql.test.test至此我们已经非常接近成功了,我们使用Get一步完整的类名,使用Class.forName获取Class对象,使用aClass.isInterface()和aClass.getAnnotation(Bean.class)让我判断它是否真的是一个接口,是否包含@Bean注解,并且它不是接口并且包含@Bean注解,我们获取它的实例并将其添加到映射com.wql.daoImpl.userDaoImplcom.wql.serviceImpl.userServiceImpltest:userDaoImpl:packagecom.wql.daoImpl;importcom.wql.Annotation.Bean;importcom.wql.dao.userDao;@BeanpublicclassuserDaoImplimplementsuserDao{@Overridepublicvoidtest(){System.out.println("Successfulautowiring");}}通过@Bean成功注入3.@Autowiredautowiringautowiring必须有东西才能安装,所以我们只能先遍历map集合,获取map中已经存在的对象的Class,然后获取他们的字段,判断字段中是否包含@Autowired注解,如果有,则进行自动组装lang.annotation.Target;@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public@interfaceMyAutowired{}userDaoImpl类代码实现:packagecom.wql.daoImpl;importcom.wql.Annotation.Bean;importcom.wql.dao.userDao;@BeanpublicclassuserDaoImplimplementsuserDao{@Overridepublicvoidtest(){System.out.println("自动装配成功");}}serviceImpl:packagecom.wql.serviceImpl;importcom.wql.Annotation.MyAutowired;importcom.wql.Annotation.Bean;importcom.wql.dao.userDao;importcom.wql.service.userService;@BeanpublicclassuserServiceImplimplementsuserService{@MyAutowiredpublicuserDaouserDao;@Overridepublicvoidtest(){userDao.test();}}MyApplicationContext类代码实现://通过注解组装beanpublicvoidinitAnnotationSpringIOC(){filepath=MyApplicationContext.class.getClassLoader().getResource("").getFile();//得到工程路径后System.out.println(filepath);loadOne(newFile(filepath));AnnotationAutowired();}//自动组装privatevoidAnnotationAutowired(){for(Map.Entryentry:map.entrySet()){Objectobj=entry.getValue();ClassaClass=obj.getClass();Field[]fields=aClass.getDeclaredFields();for(Fieldfield:fields){field.setAccessible(true);if(field.getAnnotation(MyAutowired.class)!=null){try{field.set(obj,map.get(field.getType()));}catch(Exceptione){e.printStackTrace();}}}}}test自动组装测试成功总结最后附上MyApplicationContext的所有代码:packagecom。wql.application;导入com.wql.Annotation.Bean;导入com.wql.Annotation.MyAutowired;导入java.io.File;导入java.io.InputStream;导入java.lang.reflect.Field;导入java.util。HashMap;importjava.util.Map;importjava.util.Properties;importjava.util.Set;publicclassMyApplicationContext{//模拟IOC容器privateMapmap=newHashMap<>();privateStringResourcePath;privateStringfilepath;publicMyApplicationContext(){}publicMyApplicationContext(StringresourcePath){ResourcePath=resourcePath;}//获取未知类型的对象(通过map收集)publicTgetBean(Classclazz){return(T)map.get(clazz);}//通过属性中存储的键值对获取Class对象,注入到map集合中publicvoidinitXMLSpringIOC(){try{InputStreamstream=MyApplicationContext.class.getClassLoader().getResourceAsStream(ResourcePath);Propertiesproperties=newProperties();properties.load(stream);//获取内容Setkeys=properties.keySet();for(Objectkey:keys){//Class:实例map.put(Class.forName(key.toString()),Class.forName(properties.getProperty(key.toString())).newInstance());}}catch(Exceptione){e.printStackTrace();}}//通过注解组装beanpublicvoidinitAnnotationSpringIOC(){filepath=MyApplicationContext.class.getClassLoader().getResource("").getFile();//获取项目路径后System.out.println(filepath);loadOne(newFile(filepath));AnnotationAutowired();}privatevoidloadOne(Filefileparent){if(fileparent.isDirectory()){//获取sub-filesFile[]files=fileparent.listFiles();if(files.length==0||files==null){return;}else{//其下的文件夹不为空for(Filefile:files){if(file.isDirectory()){loadOne(file);}else{try{Stringoldpath=file.getAbsolutePath().substring(filepath.length()-1,file.getAbsolutePath().length());if(oldpath.contains(".class")){Stringnewpath=oldpath.replaceAll("\\",".").replace(".class","");ClassaClass=Class.forName(newpath);//模拟组装beanif(!aClass.isInterface()){if(aClass.getAnnotation(Bean.class)!=null){//证明这个类包含Bean注解,添加到mapmap.put(aClass.getInterfaces()[0],aClass.newInstance());}}}}catch(Exceptione){e.printStackTrace();}}}}}}//自动程序集privatevoidAnnotationAutowired(){for(Map.Entryentry:map.entrySet()){Objectobj=entry.getValue();ClassaClass=obj.getClass();Field[]fields=aClass.getDeclaredFields();for(Fieldfield:fields){field.setAccessible(true);if(field.getAnnotation(MyAutowired.class)!=null){try{field.set(obj,map.get(字段.getType()));}catch(Exceptione){e.printStackTrace();}}}}}}