日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

模拟springIOC容器的annotation

發布時間:2024/4/13 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 模拟springIOC容器的annotation 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

spring 有兩大核心 IOC和AOP。 ?IOC (inversion of control) 譯為 控制反轉,也可以稱為 依賴注入 ; AOP(Aspect Oriented Programming)即面向切面編程。

我們此次所模仿的是?spring IOC?中的 Annotation 版的自動裝配;Spring 在2.5版本后 引入了?@Autowired?以及一系列的 Annotation,它可以對類成員變量、方法及構造函數進行注解,完成自動裝配的工作。相比于我們繁瑣的傳統xml配置注入來說,Annotation 的自動裝配會更加簡便,給需要注入的屬性或方法加上** @Autowired** 后即可對該屬性或方法進行自動注入,如果我們的屬性是接口,

?或者是一個父類的話,我們可以再加一個?@Qualifier?并為其設置一個value 即可指定該接口或該父類所指定的實現類或子類(對應于實現類或父類中?@Component?中的value)。

一、實現功能:

Annotation版的spring自動裝配

二、實現思路:

spring ioc 底層也是基于java反射技術實現的,本次模仿牽扯到很多關于java反射方面的知識,如果各位小伙伴對java反射還不是太了解的的話可能這篇博文你會聽的暈乎乎的噢!

  • 創建我們需要的Annotation?@Component @Autowired @Qualifier

  • 創建ApplicationContext接口,里面一個getBean()方法,創建AnnotationConfigApplicationContext類實現ApplicationContext接口

  • AnnotationConfigApplicationContext的構造方法會接收一個包名,然后負責把這個包下面的所有java類的路徑拿出來,再將路徑處理一下即可得到類全名,并放入集合,再通Class.forName(類全名)得到所有Java類的Class 并放入集合

  • 遍歷集合所有的class判斷該類上是否加了@Component, 再把加了@Component?的Class放置一個集合,然后再判斷Class 的@Component?是否存在value,如果存在,則把valuevalue作為key 該Class作為value 放置一個Map集合

  • AnnotationConfigApplicationContext重寫的?getBean()??接收一個類的Class, 得到接收Class的實例對象,進行相應屬性的依賴注入,解決完依賴后return實例對象。得到Class所有的Field,遍歷Field是否加了?@Autowired,如果加了?@Autowired再次判斷是否加了?@Qualifier,如果加了?@Qualifier?,用?@Qualifier的value去Map集合 得到對應的Class,然后使用Field.set為實例對象的該Field賦值如(field.set(object,value))value為回調本方法后的返回值(本方法會返回Class的實例), 如果沒有加?@Qualifier?則得到該Field的類型的Class ,使用Field.set為實例對象的該Field賦值,值為回調本方法后的返回值。待處理完所有的依賴注入后返回實例對象。

三、Java代碼:

創建需要的Annotation

1、創建@Component

package com.custom.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(value={ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface Component {public String value() default ""; }

2、創建@Autowired

package com.custom.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Target(value={ElementType.FIELD,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface Autowired { }

3、創建@Qualifier

package com.custom.annotation; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME) public @interface Qualifier {public String value() default ""; }

主要功能實現

1、創建ApplicationContext接口

package com.custom.controller; public interface ApplicationContext {public Object getBean(Class clazz); }

2、創建AnnotationConfigApplicationContext類

package com.custom.controller; import java.io.File; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import com.custom.annotation.Autowired; import com.custom.annotation.Component; import com.custom.annotation.Qualifier; import com.custom.exception.CustomException; import com.example.Hello; import com.example.World;public class AnnotationConfigApplicationContext implements ApplicationContext {private String projectPath=this.getClass().getResource("/").getPath();//項目路徑private List<Class> clazzList;//包下所有類private List<String> filePaths;//包下所有文件名private Map<String,Class> existComponentClassMap;//含有@Component注解的類private Map<String,Class> existComponentValueClassMap;//含有@Qualifier值的類public AnnotationConfigApplicationContext(String... strings){clazzList=new ArrayList<Class>();existComponentClassMap=new HashMap<>();existComponentValueClassMap=new HashMap<>();for (String tempPackageName : strings) {//遍歷傳進來的包filePaths=getFileName(projectPath+(tempPackageName.replaceAll("[.]","/")));try {//把掃描到包下的類都放入clazzList集合clazzList.addAll(getFileClass(filePaths)) ;//遍歷所有類,看是否加了@Component isComponent();} catch (Exception e) {// TODO Auto-generated catch block e.printStackTrace();}}}@Overridepublic Object getBean(Class clazz) {try {//判斷傳入的類是否加了@Componentif(existComponentClassMap.get(clazz.getName())!=null){//解決clazz依賴并返回clazz的實例return isAutowired(clazz);}else{//拋出異常throw new CustomException("not found "+clazz.getName()+" mapping class");}} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}return null;}//循環判斷是否加了@Componentprivate void isComponent(){for (Class tempClass : clazzList) {//判斷該類是否加有@Componentif(tempClass.isAnnotationPresent(Component.class)){//把加了@Component注解的類放入集合existComponentClassMap.put(tempClass.getName(),tempClass);Component component=(Component)tempClass.getAnnotation(Component.class);//得出@Component中的valueString componentValue=component.value();//判斷@Component中的value是否有值if(componentValue.length()>0){//把@Component中的value和當前類的class放入Map集合中existComponentValueClassMap.put(componentValue, tempClass);}}}}//循環判斷加了Component注解類里面是否有加了@Autowired注解,和@Qualifier的屬性或方法private Object isAutowired(Class clazz) throws Exception{//得到傳入clazz的實例Object object=clazz.newInstance();//得到clazz的所有的屬性Field fields[]=clazz.getDeclaredFields();//遍歷所有屬性for (Field field : fields) {//判斷該屬性是否加了@Autowiredif(field.isAnnotationPresent(Autowired.class)){//判斷該屬性是否加了@Qualifierif(field.isAnnotationPresent(Qualifier.class)){Qualifier qualifier=field.getAnnotation(Qualifier.class);//使用@Qualifier的值從Map集合中拿出對該值對應的classClass Tempclazz=existComponentValueClassMap.get(qualifier.value());if(Tempclazz!=null){//為屬性設置賦值權限field.setAccessible(true);//為實例出來的clazz對象的該屬性賦值,賦值之前再次遞歸調用本方法,傳入該屬性類型的classfield.set(object,isAutowired(Tempclazz));}else{throw new CustomException("not found "+qualifier.value()+" mapping class");}}else{//得到該屬性的類型Class fieldType=field.getType();Class Tempclazz=existComponentClassMap.get(fieldType.getName());if(Tempclazz!=null){field.setAccessible(true);field.set(object,isAutowired(Tempclazz));}else{throw new CustomException("not found "+fieldType.getName()+" mapping class");}}}}return object;}//得到指定包下面的所有java文件路徑public List<String> getFileName(String packgePath){List<String> filePaths=new ArrayList<>();String filePath=packgePath;File file=new File(filePath);//判斷是否為目錄if(file.isDirectory()){//得到包下所有文件File files[]=file.listFiles();for (File file2 : files) {//判斷是否為目錄if(file2.isDirectory()){//遞歸調用filePaths.addAll(getFileName(file2.getPath()));}else{//如果后綴為class則把該文件路徑放入集合if(file2.getName().substring(file2.getName().lastIndexOf(".")+1).equals("class")){filePaths.add(file2.getPath());}}}}return filePaths;}//返回所有java文件的classpublic List<Class> getFileClass(List<String> filePath) throws ClassNotFoundException{List<Class> list=new ArrayList<Class>();for (String tempFileName : filePath) {//從項目路徑之后開始截取java文件名String tempClassName=tempFileName.substring(projectPath.length()-1);//把路徑中的“\”替換成“.”例如“com\test\test.java”替換后“com.test.test.java”tempClassName=tempClassName.replaceAll("\\\\",".");//再把后面的“.java”截取掉 然后使用Class.forName得到該類的class,并放入集合list.add(Class.forName(tempClassName.substring(0,tempClassName.lastIndexOf("."))));}return list;} }

當然Annotation 自動裝配也不是特別完美的,就比如我們要自動裝配一個類的話 ?必須為其設置?@Component?,比如我們要實例一些第三方jar包中的類,我們總不可能讓第三方為我們加上@Component吧,當然 這是不現實的,不過如果你面子夠大的話還是可以試一下的哈!所以在我們的實際開發中結合Annotation和xml使用才是最佳王道、當然,前者是基于普通是ssm項目、如果是基于springboot來的話 我們要配合javaConfig配置模式

?

總結

以上是生活随笔為你收集整理的模拟springIOC容器的annotation的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。