Spring IOC容器的简单实现

IOC:

Inverse of Control(控制反转) 将原本在程序中手动创建对象的控制权,交由Spring框架来管理 若要使用某个对象,只需要从 Spring 容器中获取需要使用的对象,不关心对象的创建过程,也就是把创建对象的控制权反转给了Spring框架。

 

Github:https://github.com/starcold/StarColdIOC

github只有src下的文件和pom.xml文件,代码带有详细的注释,请自取;

github用不了的可以点这里

项目结构目录如下:

annotation实现一些需要的注解

@Retention(RetentionPolicy.RUNTIME)//运行时注解
@Target(ElementType.FIELD)//作用在字段上
@Documented
public @interface Autowire {
    //注解有一个名为 value 的可选参数。不设置的话默认为“”。如果没有后面的 default "",则表示这是一个必须的参数。不指定的话会报错。
    String value() default "";
}


@Retention(RetentionPolicy.RUNTIME)//运行时注解
@Target(ElementType.TYPE)//作用在类上
@Documented
public @interface Component{
    String value() default "";
}

@Retention(RetentionPolicy.RUNTIME)//运行时注解
@Target(ElementType.TYPE)//作用在类上
@Documented
public @interface Controller {
    String value() default "";
}

@Retention(RetentionPolicy.RUNTIME)//运行时注解
@Target(ElementType.PARAMETER)//作用在方法参数上面
@Documented
public @interface RequestParam {
    String value() default "";
}

@Retention(RetentionPolicy.RUNTIME)//运行时注解
@Target({ElementType.TYPE, ElementType.METHOD})//作用在类和方法,参考springmvc
@Documented
public @interface RequsetMapping {
    String value() default "";
}

support下AnnotationApplicationContext继承了ApplicationContext和BeanRegister;相当于BeanFactory。

Interfaces下定义了两个接口ApplicationContext和BeanRegister

public interface ApplicationContext {
    Object getBean(String id);
    <T>T getBean(String id, Class<T> clazz);
    Map<String, Object> getBeans();

}


public interface BeanRegister {
    void registBeanDefinition(List<BeanDefinition> bds);
    void registInstanceMapping(String id, Object instance);
}

一些默认的工厂实现

public class BeanCreater{
    private BeanRegister register;

    public BeanCreater(BeanRegister register){
        this.register = register;
    }

    public void create(List<BeanDefinition> bds){
        for(BeanDefinition bd : bds){
            doCreate(bd);
        }
    }

    public void doCreate(BeanDefinition bd){
        Object instance = bd.getInstance();
        this.register.registInstanceMapping(bd.getId(), instance);
    }
}


public class BeanDefinition {
    private String id;
    private Class clazz;

    public BeanDefinition(String id, Class clazz){
        this.id = id;
        this.clazz = clazz;
    }

    public Object getInstance(){
        try{
            return clazz.newInstance();
        }
        catch(Exception e){
            e.printStackTrace();
        }
        return null;
    }

    //region Getter && Setter

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public Class getClazz() {
        return clazz;
    }

    public void setClazz(Class clazz) {
        this.clazz = clazz;
    }

    //endregion
}

public class BeanDefinitionGenerator {
    public static List<BeanDefinition> generte(String classname){
        try{
            Class clazz = Class.forName(classname);
            String[] ids = generateIds(clazz);

            if(ids==null){
                return null;
            }

            List<BeanDefinition> list = new ArrayList<BeanDefinition>();

            for(String id:ids){
                list.add(new BeanDefinition(id, clazz));
            }
            return list;
        }
        catch(ClassNotFoundException e){
            e.printStackTrace();
        }
        return null;
    }

    private static String[] generateIds(Class clazz){
        String[] ids = null;

        if(clazz.isAnnotationPresent(Controller.class)){
            ids = new String[]{clazz.getName()};
        }
        else if(clazz.isAnnotationPresent(Component.class)){
            Component component = (Component) clazz.getAnnotation(Component.class);
            String value = component.value();

            if(!"".equals(value)){
                ids = new String[]{value};
            }
            else{
                Class<?>[]  interfaces = clazz.getInterfaces();
                ids = new String[interfaces.length];
                for(int i = 0; i < interfaces.length; i++){
                    ids[i] = interfaces[i].getName();
                }
                return ids;
            }
        }
        return ids;
    }
}


public class BeanDefinitionParser {
    public static final String SCAN_PACKAGE = "scanPackage";
    private BeanRegister register;

    public BeanDefinitionParser(BeanRegister register){
        this.register = register;
    }

    public void parse(Properties properties){
        String packageName = properties.getProperty(SCAN_PACKAGE);
        doRegister(packageName);
    }

    
    public void doRegister(String packageName){
        URL url = getClass().getClassLoader().getResource("./" + packageName.replace(".","/"));
        File dir = new File(url.getFile());

        for(File file:dir.listFiles()){
            if (file.isDirectory()){
                doRegister(packageName + "." + file.getName());
            }
            else{
                String className = packageName + "." + file.getName().replaceAll(".class", "").trim();
                
                List<BeanDefinition> definitions = BeanDefinitionGenerator.generte(className);
                if(definitions == null)continue;
                this.register.registBeanDefinition(definitions);
            }
        }
    }
}

public class Populator {
    public Populator(){

    }

    public void populator(Map<String, Object> instanceMapping) {
        if (instanceMapping.isEmpty()) return;
        for (Map.Entry<String, Object> entry : instanceMapping.entrySet()) {
            Field[] fields = entry.getValue().getClass().getDeclaredFields();
            for (Field field : fields) {
                if (!field.isAnnotationPresent(Autowire.class)) continue;
                Autowire autowire = field.getAnnotation(Autowire.class);
                String id = autowire.value();
                if ("".equals(id)) id = field.getType().getName();
                field.setAccessible(true);
                try {
                    field.set(entry.getValue(), instanceMapping.get(id));
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

最后的测试类

@Controller
public class MyController {
    @Autowire("myservice")
    private MyService service;

    public void test(){
        service.print("test success!");
    }

    public static void main(String[] args){
        ApplicationContext context = new AnnotationApplicationContext("applicationContext.properties");
        MyController controller = context.getBean("com.starcold.ioc.MyController", MyController.class);
        controller.test();
    }
}

@Component("myservice")
public class MyService {
    public void print(String s){
        System.out.println(s);
    }
}

参考博客:

Spring源码--IOC容器实现(6)--Bean依赖注入

自己实现spring(一) —— ioc容器实现

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值