随手敲代码——IOC猜想(终极版)

这个版本中我自定义了一个配置文件,并在其中定义了需要扫描的包,然后对包中的文件进行自动注入。个人感觉这和spring的IOC模型已经很像了,提供一个xml给用户进行配置,其余事情都交给容器进行管理
上代码

package com.kevindai.testioc;

import org.springframework.beans.factory.annotation.Autowired;


public class PrivateCar {
    private String color;
    @Autowired
    private Engine engine;
    private Integer i;
    protected void drive(){
        System.out.println("drive my " +  color + " car!");
        System.out.println("THE engine brand : " + engine.brand);
        System.out.println("init int " + i);
    }

}
package com.kevindai.testioc;

public class Engine {
    public static String brand = "benz";
}

XML配置(这个可以理解为是applicationContext.xml)

<?xml version="1.0" encoding="UTF-8"?>
<xml-body>
    <component-scan>
        <value>com.kevindai.testioc.*</value>
    </component-scan>
</xml-body>
package com.kevindai.test;

import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;

public class AbstactReflect {
    @SuppressWarnings("unchecked")
    public static void main(String[] args) throws Exception {
        //通过jdom解析自定义的XML,来获取要加载哪些类
        ResourcePatternResolver rl = new PathMatchingResourcePatternResolver();
        Resource resource = rl.getResource("classpath:myioc.xml");
        File myiocXml = resource.getFile();

        SAXBuilder saxBuilder = new SAXBuilder();
        Document doc = saxBuilder.build(myiocXml);

        Element root = doc.getRootElement();
        List<Element> allChildren = root.getChildren();
        for(Element e : allChildren){
            //获取配置好的要扫描的路径
            String packageDirName = e.getChild("value").getText();
            if(packageDirName.endsWith(".*")){
                packageDirName = packageDirName.substring(0,packageDirName.indexOf(".*"));
            }
            //因配置中配置的都是类似com.kevindai.**的,因此要把.换成*
            String packagePathName = packageDirName.replace(".", "/");

            resource = rl.getResource("classpath:/" + packagePathName);
            File dir = resource.getFile();
            if(!dir.exists()){
                System.out.println("can't not find " + packageDirName + " in myioc.xml");
            }else{
                File[] fileList = dir.listFiles();
                //获取配置文件中配置的要扫描的包下面的所有class文件
                for(File file : fileList){
                    //通过反射机制获取类、方法
                    ClassLoader cl = Thread.currentThread().getContextClassLoader();
                    Class<?> clazz = cl.loadClass(packageDirName + "." + file.getName().substring(0,file.getName().indexOf(".class")));
                    Object o = clazz.newInstance();

                    Field[] fields = clazz.getDeclaredFields();
                    for(Field f : fields){
                        //这一步的意义是找到有注解的属性,并完成自动找到该属性对应的实体,并完成注入
                        //这里其实可以自定义注解,然后用扫描到自定义注解的属性才去注入,但我这里只是演示,因此不做自定义注解及后续判断
                        Annotation[] annotation = f.getDeclaredAnnotations();
                        if(annotation.length > 0){
                            if(!f.isAccessible()){
                                f.setAccessible(true);
                            }
                            //找到当前属性的类型并新建一个对象赋值给属性(类似spring注入一个实体)
                            Class<?> cla = f.getType();
                            Object object = cla.newInstance();
                            //这样注入有一个问题,当属性没有无参构造函数(如Integer)时会有问题,且不用对基本数据类型这样注入
                            f.set(o,object);
                        }
                    }

                    Method[] methods = clazz.getDeclaredMethods();
                    for(Method m :methods){
                        if(!m.isAccessible()){
                            m.setAccessible(true);
                        }
                        //反射机制制定方法参数类型
                        Class<?>[] cla = m.getParameterTypes();
                        Object[] methodArgs = new Object[m.getParameterTypes().length];
                        int i = 0;
                        for(Class<?> c : cla){
                            methodArgs[i] = c.cast(c.newInstance());
                            i++;
                        }

                        m.invoke(o,methodArgs);
                    }

                }
            }
        }

    }
}

只想对自己刷一行6
***************分割线******************
666666666666666666666666666666666

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值