Spring -- IOC 手写

发布时间 2024-01-12 23:20:43作者: 弯弓射雕的男人

. java 反射

Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。简单来说,反射机制指的是程序在运行时能够获取自身的信息。

要想解剖一个类,必须先要获取到该类的Class对象。而剖析一个类或用反射解决具体的问题就是使用相关API**(1)java.lang.Class(2)java.lang.reflect**,所以,Class对象是反射的根源。

 

 

手写IOC

package Bean;

import org.springframework.context.annotation.Bean;

import javax.print.DocFlavor;
import java.io.File;
import java.io.IOException;

import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

public class AnnApplicationContextIMPL implements ApplicationContext{
    /*创建map防止bean对象*/
    private  Map<Class,Object> beanfactory=new HashMap<>();
    private  static String  rootPath;
    @Override
    public Object GetBean(Class clazz) {
        return beanfactory.get(clazz);
    }

    //设置包扫描规则
    //当前包 及其子包 如果有注解 就通过反射进行实例化
    public AnnApplicationContextIMPL(String basePackage){
       //public static void pathdemo1(String basePackage){
        try {
        //1.把里面的。换成\
       String PackagePath= basePackage.replaceAll("\\.","\\\\");
        //2.获取包的绝对路径

            Enumeration urls= Thread.currentThread().getContextClassLoader().getResources(PackagePath);
            while (urls.hasMoreElements()){
                URL url= (URL) urls.nextElement();
               String filePath=  URLEncoder.encode(url.getFile(),"utf-8");
                System.out.println("filePath = " + filePath);
                //获取包相对路径  截取
                rootPath=filePath.substring(0,filePath.length()-basePackage.length());
                //包扫描
                leanBean(new File(filePath));
            }
        } catch (IOException | ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    //包扫描的过程
    private  void leanBean(File file) throws ClassNotFoundException {
        //1.判断当前内容是不是文件夹

        if (file.isDirectory()){
            //2.获取文件夹的所有内容 包括子文件夹
            File[] childrenfile=file.listFiles();
            //3.判断是否为空
            if (childrenfile==null||childrenfile.length==0){
                return;
            }
            //4.如果不为空 遍历所有内容
            for (File child:childrenfile){
                //4.1.遍历每个file对象,继续判断是否为空,递归。
                if (child.isDirectory()){
                    leanBean(child);
                }else {
                    //4.2.得到的flie如果不是文件夹,是文件。.
                    //4.3.得到包路径+类名称-----即是字符串截取
                    String pathWithClass =
                            child.getAbsolutePath().substring(rootPath.length()-1);
                    //4.4.判断当前文件类型 是否是.class类型
                   if (pathWithClass.contains(".class")){
                       //4.5.如果是.class类型 如果是 把路径\替换成. 把.class去掉
                       String allName=pathWithClass.replaceAll("\\\\",".").
                               replace(".class","");


                       //4.6.判断类上是否有注解@bean,如果有进行实例化

                            //4.6.1 获取类的class 对象
                            Class<?> clazz = Class.forName(allName);
                            //4.6.2判断是不是接口
                            if(clazz.isInterface()){
                            //判断上面是否有注解@
                                Bean annotation = clazz.getAnnotation(Bean.class);
                                if (annotation!=null){
                                    try {
                                        Object instance = clazz.getConstructor().newInstance();
                                        //4.7把实例化之后的内容 放入Map
                                        //4.7.1 判断当前类是否有接口 让class作为map的类
                                        if (clazz.getInterfaces().length>0){
                                            beanfactory.put(clazz.getInterfaces()[0],instance);
                                        }else{
                                            beanfactory.put(clazz,instance);
                                        }

                                    } catch (InstantiationException e) {
                                        throw new RuntimeException(e);
                                    } catch (IllegalAccessException e) {
                                        throw new RuntimeException(e);
                                    } catch (InvocationTargetException e) {
                                        throw new RuntimeException(e);
                                    } catch (NoSuchMethodException e) {
                                        throw new RuntimeException(e);
                                    }
                                }

                            }



                   }

                }
            }


        }


    }

    
}