base - spring ioc原理-扫描注解创建单例对象的简化实现

105 阅读1分钟

世界上并没有完美的程序,但是我们并不因此而沮丧,因为写程序就是一个不断追求完美的过程。

  1. 引入依赖
<dependency>
    <groupId>cn.hutool</groupId>
     <artifactId>hutool-all</artifactId>
     <version>5.3.7</version>
 </dependency>
  1. 创建注解
package com.test.demo.ioc;

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 HouComponent {
}
  1. 添加注解
package com.test.demo.ioc;

@HouComponent
public class HelloService {
}
  1. 创建容器
package com.test.demo.ioc;

import cn.hutool.core.util.ClassUtil;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public class AnnoApplicationContext {
    /**
     * 单例对象存储器
     */
    private Map<String, Object> singleObjects = new ConcurrentHashMap<>(16);

    /**
     * 包名
     */
    private String packageName;
    public AnnoApplicationContext(String packageName){
        this.packageName = packageName;
    }

    /**
     * 获取Bean
     * @param id
     * @return
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public Object getBean(String id) throws InstantiationException, IllegalAccessException {
        if(!singleObjects.containsKey(id)){
            scanPackage(id);
        }
        return singleObjects.get(id);
    }

    /**
     * 包扫描,扫描指定注解的类并创建对象放入到map中
     * @param id
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public void scanPackage(String id) throws IllegalAccessException, InstantiationException {
        Set<Class<?>> classes = ClassUtil.scanPackageByAnnotation(packageName, HouComponent.class);
        for(Class<?> clazz: classes){
            String classId = clazz.getSimpleName().substring(0,1).toLowerCase()+clazz.getSimpleName().substring(1);
            if(id.equals(classId)){
                singleObjects.put(classId, clazz.newInstance());
            }
        }
    }

    /**
     * 测试
     * @param args
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public static void main(String[] args) throws IllegalAccessException, InstantiationException {
        AnnoApplicationContext context = new AnnoApplicationContext(AnnoApplicationContext.class.getPackage().getName());
        Object o = context.getBean("helloService");
        System.out.println(o);
    }
}

结果

com.test.demo.ioc.HelloService@6f1fba17

在这里插入图片描述