8.refresh-invokeBeanFactoryPostProcessor方法解析(下)

【接上文】

  • @ImportResource
// Process any @ImportResource annotations
AnnotationAttributes importResource =
        AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
    String[] resources = importResource.getStringArray("locations");
    Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
    for (String resource : resources) {
        String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
        configClass.addImportedResource(resolvedResource, readerClass);
    }
}

这里的处理相对简单,就是把注解里的location解析出来,做变量替换然后保存到configClass的ImportResource map中去。
调用的位置是在parse解析完了以后通过loadBeanDefinition…的方法调用的,这个后面再说。

  • @Bean
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
    configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}


/**
 * Retrieve the metadata for all <code>@Bean</code> methods.
 * 获取所有@Bean注解的方法元信息
 */
private Set<MethodMetadata> retrieveBeanMethodMetadata(SourceClass sourceClass) {
    AnnotationMetadata original = sourceClass.getMetadata();
    Set<MethodMetadata> beanMethods = original.getAnnotatedMethods(Bean.class.getName());
    //判断方法集合是否超过两个,并且类的元数据是StandardAnnotationMetadata实例,则从ASM内获取声明的方法顺序
    if (beanMethods.size() > 1 && original instanceof StandardAnnotationMetadata) {
        try {
            // 尝试通过ASM从类文件判断方法的顺序...因为,JVM的标准反射库获取的方法顺序是随机的,
            // 甚至泡在相同JVM的不同应用返回的顺序也会不一致
            AnnotationMetadata asm =
                    this.metadataReaderFactory.getMetadataReader(original.getClassName()).getAnnotationMetadata();
            Set<MethodMetadata> asmMethods = asm.getAnnotatedMethods(Bean.class.getName());
            if (asmMethods.size() >= beanMethods.size()) {
                Set<MethodMetadata> selectedMethods = new LinkedHashSet<>(asmMethods.size());
                for (MethodMetadata asmMethod : asmMethods) {
                    for (MethodMetadata beanMethod : beanMethods) {
                        if (beanMethod.getMethodName().equals(asmMethod.getMethodName())) {
                            selectedMethods.add(beanMethod);
                            break;
                        }
                    }
                }
                if (selectedMethods.size() == beanMethods.size()) {
                    // All reflection-detected methods found in ASM method set -> proceed
                    beanMethods = selectedMethods;
                }
            }
        }
        catch (IOException ex) {
            logger.debug("Failed to read class file via ASM for determining @Bean method order", ex);
            // No worries, let's continue with the reflection metadata we started with...
        }
    }
    return beanMethods;
}

解析@Bean注解的方法,存到configClass的beanMethod对应的map。

  • interface
/**
 * Register default methods on interfaces implemented by the configuration class. 
 * 获取接口上的bean注解方法
 */
private void processInterfaces(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {
    for (SourceClass ifc : sourceClass.getInterfaces()) {
        Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(ifc);
        for (MethodMetadata methodMetadata : beanMethods) {
            if (!methodMetadata.isAbstract()) {
                // A default method or other concrete method on a Java 8+ interface...
                configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
            }
        }
        processInterfaces(configClass, ifc);
    }
}

private final Set<BeanMethod> beanMethods = new LinkedHashSet<>();

public void addBeanMethod(BeanMethod method) {
    this.beanMethods.add(method);
}

获取接口及及包含默认实现的接口方法, 然后封装成BeanMethod 添加到configClass的beanMethods中。

后续就是解析父类,添加到knownSuperClasses

// Process superclass, if any
if (sourceClass.getMetadata().hasSuperClass()) {
    String superclass = sourceClass.getMetadata().getSuperClassName();
    if (superclass != null && !superclass.startsWith("java") &&
            !this.knownSuperclasses.containsKey(superclass)) {
        this.knownSuperclasses.put(superclass, configClass);
        // Superclass found, return its annotation metadata and recurse
        return sourceClass.getSuperClass();
    }
}

到这里ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法就解析完成了。

【NEXT】

对invokeBeanFactoryPostProcessor这个方法的整体脉络做整体审视和总结。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是在CentOS 7上完成这些要求的具体步骤: 1. 安装BIND软件包: ``` yum install bind bind-utils -y ``` 2. 编辑主DNS服务器的配置文件`/etc/named.conf`,添加以下内容: ``` acl "trusted" { 192.168.1.0/24; localhost; }; options { directory "/var/named"; recursion yes; allow-query { trusted; }; forwarders { 8.8.8.8; }; }; zone "linux-xxx.com" IN { type master; file "linux-xxx.com.zone"; allow-update { none; }; }; zone "1.168.192.in-addr.arpa" IN { type master; file "1.168.192.in-addr.arpa.zone"; allow-update { none; }; }; ``` 3. 创建正向解析区域文件`/var/named/linux-xxx.com.zone`,添加以下内容: ``` $TTL 86400 @ IN SOA dns.linux-xxx.com. root.linux-xxx.com. ( 2021100101; Serial 3600; Refresh after 3 hours 900; Retry after 15 minutes 604800; Expire after 1 week 86400); Minimum TTL of 1 day @ IN NS dns.linux-xxx.com. dns.linux-xxx.com. IN A 192.168.1.学号 mail.linux-xxx.com. IN MX 10 192.168.1.180 study.linux-xxx.com. IN A 192.168.1.181 teach.linux-xxx.com. IN A 192.168.1.182 www.linux-xxx.com. IN A 192.168.1.183 ``` 4. 创建反向解析区域文件`/var/named/1.168.192.in-addr.arpa.zone`,添加以下内容: ``` $TTL 86400 @ IN SOA dns.linux-xxx.com. root.linux-xxx.com. ( 2021100101; Serial 3600; Refresh after 3 hours 900; Retry after 15 minutes 604800; Expire after 1 week 86400); Minimum TTL of 1 day @ IN NS dns.linux-xxx.com. 学号 IN PTR dns.linux-xxx.com. 180 IN PTR mail.linux-xxx.com. 181 IN PTR study.linux-xxx.com. 182 IN PTR teach.linux-xxx.com. 183 IN PTR www.linux-xxx.com. ``` 5. 启动并开机自启BIND服务: ``` systemctl start named systemctl enable named ``` 6. 编辑从DNS服务器的配置文件`/etc/named.conf`,添加以下内容: ``` options { directory "/var/named"; recursion yes; allow-query { any; }; }; zone "linux-xxx.com" IN { type slave; masters { 192.168.1.学号; }; file "slaves/linux-xxx.com.zone"; }; zone "1.168.192.in-addr.arpa" IN { type slave; masters { 192.168.1.学号; }; file "slaves/1.168.192.in-addr.arpa.zone"; }; ``` 7. 启动并开机自启BIND服务: ``` systemctl start named systemctl enable named ``` 8. 在其它虚拟机和Windows主机上配置主从DNS服务器的IP地址,测试解析是否正常。 注意:在上述步骤中,需要将其中的`linux-xxx.com`和`学号`替换为具体的域名和IP地址。在创建区域文件时,需要注意修改文件名和目录路径,以避免与已有文件重名。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

泽济天下

你的鼓励是我最大的动力。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值