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

WrapClass Enrichment 处理链与各种注解 — 开篇 (2.1)

本章代码对应的Tag 为:待定

前置说明: 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的取值表达式

先来实现几个注解

  1. @Service
  2. @AutoWired
  3. @Configruation
  4. @Value

为了缩减每一篇文章的长度,本章只实现前两个。Service、AutoWired为两个基本注解。
后续会单独写一章,来实现配置文件的自动注入,即:Configuration、Value这一对注解。

@Service注解

package zm.ioc.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Service {

     /**
     * Bean ID,当name为空时,使用class的全名作为BeanID
     * @return
     */
    String name() default "";
	
	//指明是否时使用单例,默认不是单例
    boolean isSinglet() default false;
}

@AutoWired注解

package zm.ioc.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoWired {
    
}

最后,再创建两个测试用的Bean以及一个测试类

package zm.ioc.bean;
import org.apache.log4j.Logger;
import zm.ioc.annotation.AutoWired;
import zm.ioc.annotation.Service;

@Service
public class TestBeanA {
    private static final Logger log = Logger.getLogger(TestBeanA.class); 

    @AutoWired
    private TestBeanB testBeanB;

    public void say(){
        log.info("I'm Class A !!!");
        testBeanB.say();
    }
}
package zm.ioc.bean;
import org.apache.log4j.Logger;
import zm.ioc.annotation.Service;
@Service
public class TestBeanB {
    private static final Logger log = Logger.getLogger(TestBeanB.class); 

    public void say(){
        log.info("I'm Class B !!!");
    }
}

特别注意!!!!
不熟悉java注解的读者,建议网上去查看下注解中 @Retention(RetentionPolicy.RUNTIME) 的说明 RetentionPolicy有多种类型,不在这里一一赘述了,当时有一点要明确,如果不是RUNTIME,那你可能会在自己写代码时发现,怎么都无法通过反射获取到该注解,你会非常郁闷!!

WrapClass Enrichment 处理链的实现 (核心)

WrapClass Enrichment 的核心工作目标:进一步的分析处理之前收集到的Class对象
包括:过滤掉非目标Class对象,分析各种注解,记录需要自动注入的Field
所以,上一步是“广撒网”,这一步是“挑重点”。
总结下: 就是要将上面被@Service标注的TestBeanA 、TestBeanB找出来,并且记录下TestBeanA里面,有一个叫做testBeanB的Field被 @AutoWired标注了

基本思路:

  1. 遍历所有Class对象
  2. 获取所有Class上的注解,并判断是否是目标Class(即,被@Service等注解标记的Class对象)
  3. 获取目标Class的所有Field上的注解,并判断是否需要进行自动注入
  4. 将上述结果使用WrapClass对象封装起来
  5. 额外步骤,在创建WrapClass的过程中,以Class对象为key,Set为Value记录下某个class的所有子类

其中第五步是为了实现 <T> List<T> getBeansByType(Class<T> superClass) 方法,通过某个父对象类,获取所有子类Bean对象的方法

先创建处理链的接口(其中WrapClass就只一个简单的包装类,等用到时在做介绍)

package zm.ioc.classCollector;

import java.util.Set;

import zm.ioc.ioc.pojo.WrapClass;

public interface ClassEnrichment {

   /**
     * 
     * @param wrapClass 等待被处理的对象
     * @param wrapClassSet 处理完后,用于收集目标对象的容器
     * @return true: 决定是否需要执行处理链的下一个处理器
     */
    boolean enrich(WrapClass wrapClass,Set<WrapClass> wrapClassSet);
}

最后,只要去按需要,实现几个ClassEnrichment的子类并组成一个处理链就完工了,
你看,是不是很简单啊。(当然时开玩笑的啊,哈哈哈)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值