從零開始Spring05---實現(xiàn)spring注解-1

      網(wǎng)友投稿 659 2022-05-30

      前言

      前幾篇我們實現(xiàn)了配置的方式實現(xiàn)Bean的生成和注入,接下來我們將要通過注解的方式來實現(xiàn)這一過程。這是學(xué)習(xí)劉欣老師《從零開始造Spring》課程的學(xué)習(xí)筆記。在實現(xiàn)的過程中我們需要用到ASM的技術(shù),具體可以參考ASM技術(shù)

      實現(xiàn)思路

      讀取XML文件

      對指定的package 進行掃描(scan) ,找到那些標(biāo)記為@Component的類,創(chuàng)建BeanDefinition

      2.1 把一個package下面的class變成resource

      2.2 使用ASM讀取Resource中的注解

      2.3 創(chuàng)建BeanDefinition

      通過BeanDefinition創(chuàng)建Bean實例,根據(jù)注解來注入。

      具體實現(xiàn)

      我們首先來了解下相關(guān)的注解,在此處,我們首先實現(xiàn)了兩個最基本的注解@Component 注解和@Autowired 注解,注解的本質(zhì)就是元數(shù)據(jù)。我們已@Autowired為例。

      /** * * 注解本質(zhì)上就是元數(shù)據(jù), * @Target 標(biāo)注注解的使用地方 * @Documented 說注解就是一個元素,可以被文檔化 * Created by xiang.wei on 2018/7/14 * */ //構(gòu)造器,字段,方法。 @Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE}) //保留到運行時 @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Autowired { /** * Declares whether the annotated dependency is required. *

      Defaults to {@code true}. */ boolean required() default true; }

      1

      2

      3

      4

      從零開始造Spring05---實現(xiàn)spring注解-1

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      我們通過PackageResourceLoader類來將base-package 中配置的包下加載出對應(yīng)的Resource

      關(guān)鍵代碼如下:

      public Resource[] getResources(String basePackage) throws IOException { Assert.notNull(basePackage, "basePackage must not be null"); String location = ClassUtils.convertClassNameToResourcePath(basePackage); ClassLoader cl = getClassLoader(); URL url = cl.getResource(location); File rootDir = new File(url.getFile()); Set matchingFiles = retrieveMatchingFiles(rootDir); Resource[] result = new Resource[matchingFiles.size()]; int i = 0; for (File file : matchingFiles) { result[i++] = new FileSystemResource(file); } return result; }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      調(diào)試如下:

      實現(xiàn)兩個Visitor,實現(xiàn)SimpleMetaDataReader 這兩步參考ASM在Spring中的應(yīng)用

      實現(xiàn)Scanner(對ASM的抽象)

      如類圖所示,我們抽象了一個MetadataReader接口,該接口依賴于AnnotationVisitor抽象類和ClassVisitor抽象類,而AnnotationAttributesReadingVisitor類和ClassMetadataReadingVisitor類又是這兩個抽象類的實現(xiàn)。由此我們就完全隱藏了AnnotationAttributesReadingVisitor類和ClassMetadataReadingVisitor類

      測試代碼

      public class MetadataReaderTest { @Test public void testGetMetadata() throws IOException { ClassPathResource resource = new ClassPathResource("com/jay/spring/service/v4/PetStoreService.class"); MetadataReader reader = new SimpleMetadataReader(resource); AnnotationMetadata amd = reader.getAnnotationMetadata(); String annotation = Component.class.getName(); Assert.assertTrue(amd.hasAnnotation(annotation)); AnnotationAttributes attributes = amd.getAnnotationAttributes(annotation); Assert.assertEquals("petStoreService", attributes.get("value")); Assert.assertFalse(amd.isAbstract()); Assert.assertFalse(amd.isFinal()); Assert.assertEquals("com.jay.spring.service.v4.PetStoreService", amd.getClassName()); } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      ClassMetadataReadingVisitor 類

      /** * @param version * @param access * @param name * @param signature * @param supername * @param interfaces * * * 這個涉及到了Java的字節(jié)碼, 在Java字節(jié)碼中,常量池結(jié)束之后, * 有兩個字節(jié)表示訪問標(biāo)識(access_flags), * 這個標(biāo)識用于識別一些類或者接口層次的訪問信息, * 例如這個Class是類或者接口,是否為public ,abstract ,final 等等 * 對類的處理,判斷類的基本情況 * */ // @Override public void visit(int version, int access, String name, String signature, String supername, String[] interfaces) { this.className = ClassUtils.convertResourcePathToClassName(name); this.isInterface = ((access & Opcodes.ACC_INTERFACE) != 0); this.isAbstract = ((access & Opcodes.ACC_ABSTRACT) != 0); this.isFinal = ((access & Opcodes.ACC_FINAL) != 0); if (supername != null) { this.superClassName = ClassUtils.convertResourcePathToClassName(supername); } this.interfaces = new String[interfaces.length]; for (int i = 0; i < interfaces.length; i++) { this.interfaces[i] = ClassUtils.convertResourcePathToClassName(interfaces[i]); } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      AnnotationMetadataReadingVisitor 類

      public class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor implements AnnotationMetadata { private final Set annotationSet = new LinkedHashSet(4); private final Map attributeMap = new LinkedHashMap(4); public AnnotationMetadataReadingVisitor() { } @Override public AnnotationVisitor visitAnnotation(final String desc, boolean visible) { String className = Type.getType(desc).getClassName(); this.annotationSet.add(className); return new AnnotationAttributesReadingVisitor(className, this.attributeMap); } @Override public Set getAnnotationTypes() { return this.annotationSet; } @Override public boolean hasAnnotation(String annotationType) { return this.annotationSet.contains(annotationType); } @Override public AnnotationAttributes getAnnotationAttributes(String annotationType) { return this.attributeMap.get(annotationType); } @Override public boolean hasSuperClass() { return false; } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      SimpleMetadataReader類

      public SimpleMetadataReader(Resource resource) throws IOException { // 提高一點性能吧 InputStream inputStream = new BufferedInputStream(resource.getInputStream()); ClassReader classReader; try { classReader = new ClassReader(inputStream); } finally { inputStream.close(); } AnnotationMetadataReadingVisitor visitor = new AnnotationMetadataReadingVisitor(); classReader.accept(visitor, ClassReader.SKIP_DEBUG); this.annotationMetadata = visitor; this.classMetadata = visitor; this.resource = resource; }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      用ScannedGenericBeanDefinition 專門用來表達通過Scann掃描出的BeanDefiniton。

      ClassPathBeanDefinitionScanner類

      /** * 1. 給定一個package的名稱列表,例如 org.litespring.service.v4,org.litespring.dao.v4" 2. 對指定的package 進行掃描(scan),找到那些標(biāo)記為@Component 的類,創(chuàng)建ScannedGenericBeanDefinition,并且注冊到BeanFactory中。 * Created by xiang.wei on 2018/7/15 * * @author xiang.wei */ public class ClassPathBeanDefinitionScanner { private final BeanDefinitionRegistry registry; private PackageResourceLoader resourceLoader = new PackageResourceLoader(); private final Log logger = LogFactory.getLog(getClass()); private BeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator(); public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) { this.registry = registry; } /** * * @param packagesToScan 傳入的base-package 字符串 * @return */ public Set doScan(String packagesToScan) { String[] basePackages = StringUtils.tokenizeToStringArray(packagesToScan, ","); Set beanDefinitions = new LinkedHashSet(); // 對每一個basePackages進行循環(huán) for (String basePackage : basePackages) { Set candidates = findCandidateComponents(basePackage); for (BeanDefinition candidate : candidates) { beanDefinitions.add(candidate); registry.registerBeanDefinition(candidate.getID(), candidate); } } return beanDefinitions; } /** * * @param basePackage * @return */ public Set findCandidateComponents(String basePackage) { Set candidates = new LinkedHashSet(); try { // 先拿到Resource Resource[] resources = this.resourceLoader.getResources(basePackage); for (Resource resource : resources) { try { MetadataReader metadataReader = new SimpleMetadataReader(resource); // 通過metadataReader 獲取AnnotationMetadata 看看其是否有Component注解 if (metadataReader.getAnnotationMetadata().hasAnnotation(Component.class.getName())) { //實例化一個ScannedGenericBeanDefinition ScannedGenericBeanDefinition sbd=new ScannedGenericBeanDefinition(metadataReader.getAnnotationMetadata()); String beanName = this.beanNameGenerator.generateBeanName(sbd, this.registry); sbd.setId(beanName); candidates.add(sbd); } } catch (Throwable ex) { throw new BeanDefinitionStoreException("Failed to read candidate component class:" + resource, ex ); } } } catch (IOException e) { throw new BeanDefinitionStoreException("I/O failure during classpath scanning", e); } return candidates; } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      58

      59

      60

      61

      62

      63

      64

      65

      66

      67

      68

      69

      70

      71

      72

      73

      74

      75

      76

      ScannedGenericBeanDefinition類

      public class ScannedGenericBeanDefinition extends GenericBeanDefinition implements AnnotatedBeanDefinition { private final AnnotationMetadata metadata; public ScannedGenericBeanDefinition(AnnotationMetadata metadata) { super(); this.metadata = metadata; setBeanClassName(this.metadata.getClassName()); } @Override public AnnotationMetadata getMetadata() { return this.metadata; } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      對XmlBeanDefinitionReader類的修改

      private void parseComponentElement(Element element) { String basePackages = element.attributeValue(BASE_PACKAGE_ATTRIBUTE); ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(registry); scanner.doScan(basePackages); }

      1

      2

      3

      4

      5

      6

      源碼地址

      Spring

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:Voronoi圖及相關(guān)第三方庫概述
      下一篇:ModelArts模型導(dǎo)入tensorflow frozenGraph格式模型
      相關(guān)文章
      亚洲色爱图小说专区| 中文字幕亚洲一区| 亚洲av不卡一区二区三区| 亚洲欧洲在线观看| 亚洲精品中文字幕无码AV| 亚洲欧洲国产成人精品| 亚洲制服在线观看| 国产亚洲午夜高清国产拍精品 | 亚洲一卡二卡三卡| 国产精品亚洲美女久久久 | 全亚洲最新黄色特级网站 | 日韩国产精品亚洲а∨天堂免| 亚洲av无码一区二区三区不卡| 亚洲精品无码人妻无码 | 亚洲一区二区三区在线观看蜜桃 | 91亚洲国产在人线播放午夜| 亚洲无成人网77777| 亚洲国产精品lv| 青青草原精品国产亚洲av| 久久久久无码专区亚洲av | 亚洲一卡二卡三卡| 亚洲综合校园春色| 亚洲国产日韩在线视频| 亚洲国产日韩成人综合天堂| 狠狠色伊人亚洲综合网站色| 亚洲最大免费视频网| 亚洲免费人成视频观看| 亚洲日韩一区精品射精| 亚洲成人免费网站| 2020亚洲男人天堂精品| 亚洲欧美黑人猛交群| 在线观看亚洲免费| 亚洲AV无码专区在线亚| 亚洲熟妇无码八V在线播放| 亚洲国产成人久久三区| 亚洲一区二区三区写真| 亚洲?v无码国产在丝袜线观看 | 91丁香亚洲综合社区| 亚洲成a∧人片在线观看无码| 亚洲?V乱码久久精品蜜桃| 亚洲欧洲日产国码av系列天堂|