Small Spring系列五:annotation Injection(一)

栏目: Java · 发布时间: 5年前

内容简介:前两章我们已经实现了思路如下:
What a sweet burden!A joyful sorrow!

Small Spring系列五:annotation Injection(一)

概述

前两章我们已经实现了 setter 注入和 constructor 注入,本章我们来继续实现 annotation 注入。

思路如下:

  1. 读取 xml 文件
  2. 对指定 base-package 进行扫描,找到对应那些标记为 @Component 的类,创建 BeanDefinition
    • base-package 下面的 class 变成 Resource
    • 使用 ASM 读取 Resource 中的注解信息
    • 创建 BeanDefinition
  3. 通过 BeanDefinition 创建 Bean 的实例,根据注解来注入

准备测试类

AccountDao

package com.niocoder.dao.v4;

import com.niocoder.stereotype.Component;

@Component
public class AccountDao {
}

ItemDao

package com.niocoder.dao.v4;

import com.niocoder.stereotype.Component;

@Component
public class ItemDao {
}

NioCoderService

package com.niocoder.service.v4;

import com.niocoder.beans.factory.Autowired;
import com.niocoder.dao.v4.AccountDao;
import com.niocoder.dao.v4.ItemDao;
import com.niocoder.stereotype.Component;

/**
 * 测试注解
 */
@Component(value = "nioCoder")
public class NioCoderService {

    @Autowired
    private AccountDao accountDao;

    @Autowired
    private ItemDao itemDao;

    public AccountDao getAccountDao() {
        return accountDao;
    }

    public ItemDao getItemDao() {
        return itemDao;
    }
}

bean-v4.xml

增加命名空间避免元素冲突,详情参考 链接

<?xml version="1.0" encoding="UTF-8"?>
<!-- 增加namespace-->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context">

    <!-- 扫描哪个包下面的文件 -->
    <context:component-scan base-package="com.niocoder.dao.v4,com.niocoder.service.v4">

    </context:component-scan>

</beans>

Component和Autowired注解

Component 注解主要用于类名上,表明该类为一个注册到容器中的 beanAutowired 注解主要用于属性和方法(构造方法, setter 方法)上,表明该类实例化时会自动将对应的属性注入。

Component

package com.niocoder.stereotype;

import java.lang.annotation.*;

/**
 * Component 注解
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Component {

    String value() default "";
}

Autowired

package com.niocoder.beans.factory;

import java.lang.annotation.*;

/**
 * Autowired注解
 */
@Target({ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {

    boolean required() default false;
}

PackageResourceLoader

base-package 下面的 class 变成 Resource

PackageResourceLoader

/**
 * 将一个目录下的类文件加载为资源文件
 *
 * @author zhenglongfei
 */
@Log
public class PackageResourceLoader {

    /**
     * 给定一个包的路径,将包下面的文件转换为Resource
     *
     * @param basePackage
     * @return
     * @throws IOException
     */
    public Resource[] getResource(String basePackage) throws IOException {

        Assert.notNull(basePackage, "basepackage must not be null");
        String location = ClassUtils.convertClassNameToResourcePath(basePackage);
        URL url = ClassUtils.getDefaultClassLoader().getResource(location);
        File rootDir = new File(url.getFile());

        Set<File> matchingFiles = retrieveMatchingFiles(rootDir);
        Resource[] resources = new Resource[matchingFiles.size()];
        int i = 0;
        for (File file : matchingFiles) {
            resources[i++] = new FileSystemResource(file);
        }
        return resources;
    }

    private Set<File> retrieveMatchingFiles(File rootDir) throws IOException {
        if (!rootDir.exists()) {
            log.info("Skipping [" + rootDir.getAbsolutePath() + "] because is not exist");
        }

        if (!rootDir.isDirectory()) {
            log.info("Skipping [" + rootDir.getAbsolutePath() + " ] because it a Directory");
        }

        if (!rootDir.canRead()) {
            log.info("Cannot search for matching files underneath directory [" + rootDir.getAbsolutePath() +
                    "] because the application is not allowed to read the directory");
            return Collections.emptySet();
        }

        Set<File> result = new LinkedHashSet<File>(8);
        doRetrieveMatchingFiles(rootDir, result);
        return result;
    }

    protected void doRetrieveMatchingFiles(File dir, Set<File> result) throws IOException {

        File[] dirContents = dir.listFiles();
        if (dirContents == null) {
            log.info("Could not retrieve contents of directory [" + dir.getAbsolutePath() + "]");
            return;
        }
        for (File content : dirContents) {

            if (content.isDirectory()) {
                if (!content.canRead()) {
                    log.info("Skipping subdirectory [" + dir.getAbsolutePath() +
                            "] because the application is not allowed to read the directory");
                } else {
                    doRetrieveMatchingFiles(content, result);
                }
            } else {
                result.add(content);
            }

        }
    }
}

递归的读取一个指定的包目录转换为Resource

PackageResourcesLoaderTest

public class PackageResourcesLoaderTest {

    @Test
    public void testGetResource() throws Exception {
        PackageResourceLoader loader = new PackageResourceLoader();
        Resource[] resource = loader.getResource("com.niocoder.dao.v4");
        Assert.assertEquals(2, resource.length);
    }
}

测试PackageResourceLoader

debug调试

Small Spring系列五:annotation Injection(一)

代码下载

代码下载

参考资料

从零开始造Spring


以上所述就是小编给大家介绍的《Small Spring系列五:annotation Injection(一)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

SEO深度解析

SEO深度解析

痞子瑞 / 电子工业出版社 / 2014-3-1 / CNY 99.00

《SEO深度解析》以SEO从业人员普遍存在的疑问、经常讨论的问题、容易被忽视的细节以及常见的错误理论为基础,对SEO行业所包含的各方面内容进行了深入的讨论,使读者更加清晰地了解SEO及操作思路。内容分为两类:一类为作者根据自己真实、丰富的SEO经验对SEO所涉及的各种问题进行详细的讨论,主要包括SEO 基础原理剖析、SEO实操思路方法、常用工具数据剖析、竞争对手分析案例实操、网站数据分析思路指导、......一起来看看 《SEO深度解析》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

SHA 加密
SHA 加密

SHA 加密工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具