手写简单IOC

ReflectUtils.java (反射工具类)
package top.icss.ioc;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * @author cd
 * @desc 反射工具类
 * @create 2020/3/26 11:30
 * @since 1.0.0
 */
public class ReflectUtils {

    /**
     * 是否循环迭代
     */
    private final static boolean recursive = true;

    /**
     * 扫描 包下面所有Class
     * @param packageName 包名称
     * @param <T>
     * @return
     */
    public static <T> List<Class<T>> getClass(String packageName){
        List<Class<T>> list = new ArrayList<>();

        String packageNamePath = packageName;
        packageNamePath = packageNamePath.replace(".", "/");

        Enumeration<URL> resources;
        try {
            //定义一个枚举的集合 并进行循环来处理这个目录下的things
            resources = Thread.currentThread().getContextClassLoader().getResources(packageNamePath);
            //循环迭代
            while (resources.hasMoreElements()){
                URL url = resources.nextElement();
                //得到协议的名称
                String protocol = url.getProtocol();
                //如果是以文件的形式保存在服务器上
                if("file".equals(protocol)){
                    System.err.println("file类型的扫描");
                    String filePath = URLDecoder.decode(url.getFile(), "utf-8");
                    // 获取此包的目录 建立一个File
                    File dir = new File(filePath);
                    list.addAll(getClass(dir, packageName));
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        }


        return list;
    }

    /**
     * 迭代查找文件类
     * @param filePath
     * @param packageName
     * @param <T>
     * @return
     */
    private static <T> List<Class<T>> getClass(File filePath, String packageName){
        List<Class<T>> classes = new ArrayList<>();
        if(!filePath.exists()){
            return classes;
        }

        // 如果存在 就获取包下的所有文件 包括目录
        File[] files = filePath.listFiles(new FileFilter() {
            //自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件)
            @Override
            public boolean accept(File file) {
                return (recursive && file.isDirectory())
                        || file.getName().endsWith(".class");
            }
        });

        for (File file : files){
            // 如果是目录 则继续扫描
            if(file.isDirectory()){
                classes.addAll(getClass(file, packageName + "." + file.getName()));
            }else {
                // 如果是java类文件 去掉后面的.class 只留下类名
                String fileName = file.getName();
                String className = fileName.substring(0, fileName.length() - 6);
                className = packageName + "." + className;
                try {
                    //这里用forName有一些不好,会触发static方法,没有使用classLoader的load干净
                    //Class<T> cls = (Class<T>) Class.forName(className);
                    Class<T> cls = (Class<T>) Thread.currentThread().getContextClassLoader().loadClass(className);
                    classes.add(cls);
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }

        }

        return classes;
    }
public static void main(String[] args) {
        getClass("top.icss");
    }
}
MyService.java MyAutowired.java (注解类)
package top.icss.ioc.annotation;

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

/**
 * @author cd
 * @desc
 * @create 2020/3/26 14:57
 * @since 1.0.0
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyService {

    String value() default "";
}
package top.icss.ioc.annotation;

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

/**
 * @author cd
 * @desc 自动注入
 * @create 2020/3/26 14:59
 * @since 1.0.0
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MyAutowired {

    String value() default "";
}
IocContainer.java (IOC容器)
package top.icss.ioc;

import top.icss.ioc.annotation.MyAutowired;
import top.icss.ioc.annotation.MyService;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author cd
 * @desc ioc容器
 * @create 2020/3/26 14:48
 * @since 1.0.0
 */
public class IocContainer {

    private Set<Class<?>> clss = new LinkedHashSet<Class<?>>();
    private Map<String, Object> beans = new ConcurrentHashMap<String, Object>();

    /**
     * 获取类上 @MyService的注解类
     *
     * @param packageName
     */
    public void doScanner(String packageName) {
        List<Class<Object>> list = ReflectUtils.getClass(packageName);
        for (Class cls : list) {
            boolean service = cls.isAnnotationPresent(MyService.class);
            if (service) {
                clss.add(cls);
            }
        }
    }

    /**
     * 将class中的类实例化,经key-value:类名(小写)-类对象放入ioc字段中
     */
    public void doInstance() {
        for (Class cls : clss) {
            if (cls.isAnnotationPresent(MyService.class)) {
                MyService myService = (MyService) cls.getAnnotation(MyService.class);
                String beanName = "";
                if(cls.isInterface()){
                    beanName = cls.getName();
                }else {
                    beanName = ("".equals(myService.value().trim())) ? toLowerFirstWord(cls.getSimpleName()) : myService.value();
                }
                try {

                    Object instance = cls.newInstance();
                    beans.put(beanName, instance);

                    Class[] interfaces = cls.getInterfaces();
                    for (Class<?> i:interfaces){
                        beans.put(i.getName(), instance);
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        }
    }

    /**
     * 自动化的依赖注入
     */
    public void doAutowired(){
        if(beans.isEmpty()){
            return;
        }

        try {
            Set<Map.Entry<String, Object>> entries = beans.entrySet();
            for (Map.Entry<String, Object> entry: entries){
                Class<?> cls = entry.getValue().getClass();

                Field[] fields = cls.getDeclaredFields();
                //强制获取私有字段
                AccessibleObject.setAccessible(fields,true);
                for (Field f: fields){
                    if(!f.isAnnotationPresent(MyAutowired.class)){
                        continue;
                    }

                    MyAutowired myAutowired = f.getAnnotation(MyAutowired.class);
                    String beanName = "";
                    Class icls = f.getType();
                    if(icls.isInterface()){
                        beanName = icls.getName();
                    }else {
                        beanName = ("".equals(myAutowired.value().trim())) ? toLowerFirstWord(icls.getName()) : myAutowired.value();
                    }
                    //获取当前类实例
                    Object obj = entry.getValue();
                    //容器中获取字段实例
                    Object value = beans.get(beanName);

                    f.set(obj, value);

                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 获取实例
     * @param cls
     * @param <T>
     * @return
     */
    public <T> T getBean(Class<?> cls){
        MyService myService = cls.getAnnotation(MyService.class);
        String beanName = "";
        if(cls.isInterface()){
            beanName = cls.getName();
        }else {
            beanName = ("".equals(myService.value().trim())) ? toLowerFirstWord(cls.getSimpleName()) : myService.value();
        }

        return (T) beans.get(beanName);
    }

    /**
     * 将字符串首字母转换为小写
     * @param name
     * @return
     */
    private String toLowerFirstWord(String name) {
        char[] charArray = name.toCharArray();
        charArray[0] += 32;
        return String.valueOf(charArray);
    }
}

  测试

Service1.java Service2.java (接口类)
public interface Service1 {

    public void print1();
}


public interface Service2 {
    public void print2();
}
Service1Impl.java Service2Impl.java (实现类)
package top.icss.ioc.test.impl;

import top.icss.ioc.annotation.MyAutowired;
import top.icss.ioc.annotation.MyService;
import top.icss.ioc.test.Service1;
import top.icss.ioc.test.Service2;

/**
 * @author cd
 * @desc
 * @create 2020/3/26 15:45
 * @since 1.0.0
 */
@MyService
public class Service1Impl implements Service1 {

    @MyAutowired
    private Service2 service2;

    @Override
    public void print1() {
        service2.print2();
    }
}
package top.icss.ioc.test.impl;

import top.icss.ioc.annotation.MyAutowired;
import top.icss.ioc.annotation.MyService;
import top.icss.ioc.test.Service1;
import top.icss.ioc.test.Service2;

/**
 * @author cd
 * @desc
 * @create 2020/3/26 15:45
 * @since 1.0.0
 */
@MyService
public class Service2Impl implements Service2 {

    @MyAutowired
    private Service1 service1;


    @Override
    public void print2() {
        System.out.println("print2");
    }
}
IocTest.java (测试类)
public class IocTest {

    public static void main(String[] args) throws InterruptedException {
        IocContainer ioc = new IocContainer();
        ioc.doScanner("top.icss.ioc.test");
        ioc.doInstance();
        ioc.doAutowired();

        Service2 bean = ioc.getBean(Service2Impl.class);
        bean.print2();


    }
}

猜你喜欢

转载自www.cnblogs.com/iathanasy/p/12575706.html
今日推荐