自己动手写IOC容器系列 ( 二 )--- WrapClass Enrichment 处理链与各种注解 --- 2.2

WrapClass Enrichment 处理链与各种注解 — 过滤和解析 (2.2)

本章代码对应的Tag 为:v1.1.0

前置说明: IOC的总体流程

  1. 扫包,获取被目标注解标注的Class
    • 如 @Service 、@Configuration等
  2. 分析上一步得到的Class
    • 获取类上注解的相关的值
      • 例如,获取@Service(isSinglet = true) 中是否是单例的布尔值
    • 获取该类(以及父类)中被 目标注解标注的Field
      • 如 @Autowired 、 @Value等
  3. 使用反射,并依据上述获取到的所有Class、注解信息实现 getBean系列方法
    • 按BeanId获取
    • 按class name获取
    • 按某个接口,批量获取

注:以上所有注解,只有名称沿用了spring ioc中的命名。所以,发现有用法与你平时接触的不一致时,请不要惊讶。

本来打算一篇文章写完的,不过写着写着发现,有点长,就决定分几篇文章慢慢写了,这一篇,就当作WrapClass处理链的开篇吧。

WrapClass Enrichment的目的

  1. 找出所有需要被框架管理的Class,也就是那些被@Service、@Configuratoin标注的类
  2. 找出这些Bean里面,有哪些Field需要被自动注入
  3. 找出Configuration类注解中的的配置文件名称、路径
  4. 找出Configuration类中,有那些Field是被Value标注的,以及Value的取值表达式

创建WrapClass Enrichment Chian

package zm.ioc.classCollector;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.collections.CollectionUtils;

import zm.ioc.pojo.WrapClass;

public class ClassEnrichmentChian {
	// 后面再回来初始化这个List
    private List<ClassEnrichment> enrichmentChian;

    private ClassEnrichmentChian(){
    }

    public Set<WrapClass> doEnrichment(Collection<Class<?>> clazzes){
        Set<WrapClass> wrapClasses = new HashSet<>();
        if( CollectionUtils.isEmpty(clazzes)){
            return wrapClasses;
        }
		//遍历class对象,每一个对象都要被处理链处理一遍
        for(Class<?> clazz : clazzes){
            WrapClass wrapClass = WrapClass.build(clazz);
            for(ClassEnrichment classEnrichment : this.enrichmentChian){
                 classEnrichment.enrichment(wrapClass, wrapClasses);
            }
        }
        return wrapClasses;
    }
}

处理链的核心流程已经写完了,后续就是按需实现 ClassEnrichment 子类了。
注意,后面在回过来 List<ClassEnrichment> enrichmentChian 这个列表

处理链中的第一个环节,过滤

说白了,就是检查每个class对象是否有@Service注解.
下面看代码(省略了核心代码之外的内容,完整代码请注意看本文开头标记的gitee中的代码)


public class BeanClassFilter implements ClassEnrichment {
    private static final Logger log = Logger.getLogger(BeanClassFilter.class);
    public static final Set<Class<? extends Annotation>> BEAN_ANNOTATIONS = new HashSet<>();
    static{
        BEAN_ANNOTATIONS.add(Service.class);
        log.debug(String.format("The Initialization of Annotations "+
                                    "of IOC Beans finished.[%s]", BEAN_ANNOTATIONS));
    }

    @Override
    public boolean enrich(WrapClass wrapClass, Set<WrapClass> wrapClassSet) {
        boolean shouldContinue = false;
        BeanDefinitionInfo beanIdentifyInfo = this.findBeanDefinitionInfo(wrapClass);
        if(beanIdentifyInfo == null || !beanIdentifyInfo.isBeanClass){
            shouldContinue = false;
        }else{
            wrapClass.setBeanId(beanIdentifyInfo.getBeanId());
            wrapClass.setSinglet(beanIdentifyInfo.isSinglet());
            wrapClassSet.add(wrapClass);
        }
        return shouldContinue;
    }
}

处理链中的第一个环节,寻找@AutoWired注解的Field

原理同上,都是检查注解,看代码

package zm.ioc.classCollector;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.log4j.Logger;
import zm.ioc.annotation.AutoWired;
import zm.ioc.pojo.WrapClass;
import zm.ioc.pojo.WrapField;

public class AutoWiredFieldEnrichment implements ClassEnrichment{
    private static final Logger log = Logger.getLogger(AutoWiredFieldEnrichment.class);


    public static Set<Class<? extends Annotation>> AUTOWIRED_ANNOTATIONS;
    static{
        AUTOWIRED_ANNOTATIONS = new HashSet<>();
        AUTOWIRED_ANNOTATIONS.add(AutoWired.class);
    }

    @Override
    public boolean enrich(WrapClass wrapClass, Set<WrapClass> wrapClassSet) {
        // 其他非主要逻辑: 略
        for(Field field : fields){
            //获取需要自动注入的注解
            Annotation iocAnno = this.getIocAnno(field,AUTOWIRED_ANNOTATIONS);
            if( iocAnno == null){
                continue;
            }
            
            WrapField autoWiredField = new WrapField(field, wrapClass);
            autoWiredField.setIocAnno(iocAnno);
            wrapClass.addAutoWiredField(autoWiredField);
        }
        return true;
    }
}

测试一下

 public static void main(String[] args) {
        ClassCollector classCollector = ClassCollector.CLASS_COLLECTOR;
        //  URL xmlpath = 
        String rootPath = System.getProperty("user.dir") + "/target/classes/";
        
        log.info("Class collect start ! Root path is " + rootPath);
        Set<Class<?>> clazzes = classCollector.collect(rootPath);
        Set<WrapClass> wrapClasses = ClassEnrichmentChian.doEnrichment(clazzes);
        wrapClasses.stream().forEach((c)->log.info(c));
    }

测试结果如下:
[23/02/12 21:31:08:060]-zm.ioc.classCollector.ClassEnrichmentTest:19:WrapClass [beanId=, isSinglet=false, originClass=class zm.ioc.demo.bean.DemoService, autoWriedFields=[zm.ioc.pojo.WrapField@515f550a]]
[23/02/12 21:31:08:062]-zm.ioc.classCollector.ClassEnrichmentTest:19:WrapClass [beanId=, isSinglet=false, originClass=class zm.ioc.demo.bean.BeanA, autoWriedFields=[]]

注意看第一行日志中的 autoWiredFields,已正确找到。

结束

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring-IOCSpring框架的核心部分之一,它是一种设计模式,全称为Inversion of Control(控制反转)。它通过将对象的创建、依赖关系的管理和对象的生命周期交给Spring容器来实现,从而降低了组件之间的耦合度,提高了代码的可重用性和可维护性。Spring-IOC的实现主要依靠Spring容器Spring容器Spring框架的核心,它负责创建、管理和装配Bean对象,其中Bean是Spring框架中最基本的组件。 Spring-IOC的实现主要有两种方式:BeanFactory和ApplicationContext。其中,BeanFactory是Spring-IOC的基本实现,而ApplicationContext是BeanFactory的子接口,提供了更多高级特性。ApplicationContext是Spring框架中最常用的IOC容器,它除了提供BeanFactory的所有功能外,还提供了更多的企业级特性,例如AOP、事务管理、国际化、事件传播等。 下面是一个简单的Spring-IOC的例子,假设我们有一个UserService接口和一个UserServiceImpl实现类,我们可以通过Spring-IOC容器来创建和管理UserServiceImpl对象: 1.定义UserService接口和UserServiceImpl实现类 ```java public interface UserService { void addUser(User user); } @Service public class UserServiceImpl implements UserService { @Override public void addUser(User user) { // 添加用户的具体实现 } } ``` 2.在Spring配置文件中配置UserService实例 ```xml <bean id="userService" class="com.example.service.UserServiceImpl"/> ``` 3.在代码中获取UserService实例并使用 ```java ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService userService = context.getBean("userService", UserService.class); User user = new User(); userService.addUser(user); ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值