Java使用反射实现IOC容器

前面写过怎么通过Java的反射技术实现对象的创建和管理,达到IOC的效果。但是没有讲设计的思路,直接上代码,导致很多人没有思路,因此今天具体的讲IOC的编写思路理清。这里单纯的通过Java中的反射创建对象,至于扩展的部分会有提示思路
既然提到注解实现IOC,那么肯定要了解元注解的基本信息。

@Documented:被@Documented标注的类,在生成文档(doc)时,会显示@Documented注解信息。
@Inherited:可以被继承
@Target:可以声明的地方,通常为TYPE(类),FIELD(属性),METHOD(方法),
@Retention(RetentionPolicy.RUNTIME):参数有三个:CLASS,SOURCE,RUNTIME。
官方原文:注释保留策略。这种枚举类型的常量描述了保留注释的各种策略。它们与Retention元注释类型
结合使用,以指定注释要保留多长时间
1.RetentionPolicy.SOURCE —— 注释将被编译器丢弃(信息仅保留在源代码中,编译时将其忽略)。
2.RetentionPolicy.CLASS —— 注释将由编译器记录在类文件中,但不需要在运行时由 JVM 保留。这是默认行为
(编译时保留,将信息保留在CLASS文件中)。
3.RetentionPolicy.RUNTIME —— 注释将由编译器记录在类文件中,并在运行时由 JVM 保留,因此可以反射性地
读取它们(使用反射,其实就是在运行时通过JVM读取信息,类似于js脚本动态操作,这也是我们使用反射的用途)

上面简单的了解了一下元注解信息,创建注解类:@Annotation
这里即下面的例子,会参考SpringBoot的启动方式进行编写,演示一下IOC的原理,至于扩展的部分留给各位去发挥。
创建注解类:
Value普通属性值注入

@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Value {
    String value() default "";
}

Component组件(对象)创建

@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Component {
    String value() default "";//这不是数组,也不是方法,这是注解的属性声明,可以声明默认资,
    //也可不声明,String[] value()声明其为数组的形式
}

Autowared自动注入(赋值)

@Inherited
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowared {
    String value() default "";
}

AnnotationBootStrap启动类

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationBootStrap {
    boolean value() default true;
}

ComponentScanPackage类,自定义扫描包

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ComponentScanPackage {
    String value();
}

到此,基本信息创建成功。(思路:获得包路径 ---->扫描项目文件夹---->> 提取class文件 ---->>提取class全限定类名 —>> 通过Class.from创建类对象---->>获得无参构造---->>加入缓存---->遍历无参构造属性上注解信息进行赋值---->处理基本类型----->通过遍历缓存进行自动注入(注意:这里我设计的不够好,可能会产生null值,但不存在循环依赖问题)---->创建成功 )通过启动类,需要获取注解信息,因此需要获得类路径:
创建ApplicationContextAnnotationBeanFactory类(通过无参构造器创建实例,否则报错【这里可以发挥自己的想法,方法不止一个】(可以参考一下Spring解决循环依赖的缓存策略,设计三级缓存思路))

public class ApplicationContextAnnotationBeanFactory implements ApplicationContextBeanFactory {

    private Map<String, Object> objectMap;
    private List<Class> classList;
    //初始化构造器,先判断是否具备启动条件
    public ApplicationContextAnnotationBeanFactory(Class cls) throws Exception {
        if (!cls.isAnnotationPresent(AnnotationBootStrap.class)) {
            throw new RuntimeException(cls+"不是一个启动类,没有AnnotationBootStrap注解");
        } else {
            AnnotationBootStrap bootStrap = (AnnotationBootStrap) cls.getAnnotation(AnnotationBootStrap.class);
            if (bootStrap.value()) {
            //获得项目中的带有注解的Class
                this.classList = getClassList(cls);
               //获得Component标注的类对象实例
                objectMap = createObject();
            } else {
                throw new RuntimeException("AnnotationBootStrap启动类没有开启:false");
            }
        }
    }
    @Override
    public Object getBean(String name) throws ClassNotFoundException {
        return objectMap.get(name);
    }

    @Override
    public <T> T getBean(String name, Class cls) throws ClassNotFoundException {
        return (T) objectMap.get(name);
    }
    
    @Override
    public Integer getBeanSize() {
        return objectMap.size();
    }

    @Override
    public List<Object> getBeanList() {
        List<Object> list = new ArrayList<>();
        for (String beanName : objectMap.keySet()) {
            list.add(objectMap.get(beanName));
        }
        return list;
    }
    
    @Override
    public List<Class> getClassList(Class cls) throws ClassNotFoundException, FileNotFoundException {
        return new ScanPackagePath().scanPackagerPath(cls);
    }

    @Override
    public Map<String, Object> createObject() throws InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException {
        CreateFactoryBean createFactoryBean = new CreateFactoryBean();
        objectMap = createFactoryBean.getNoConstructor(classList);
        return objectMap;
    }
}

CreateFactoryBean类,创建Component标注的class


public class CreateFactoryBean {

    public Map<String, Object> getNoConstructor(List<Class> classList) throws InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException {
        Map<String, Object> objectMap = new HashMap<>();
        getNoConstructorObject(classList, objectMap);
        return objectMap;
    }
    /**
     * 创建注解无参构造的对象,将其加入容器
     */
    private void getNoConstructorObject(List<Class> classList, Map<String, Object> objectMap) throws InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException {
        for (Class aClass : classList) {
            if (aClass.isAnnotationPresent(Component.class)) {
                Component component = (Component) aClass.getAnnotation(Component.class);
                String beanName = null;
                if (component.value().equals("")) {
                    beanName = aClass.getName();//如果没有设置自定义名字,则将全路径名作为名字
                } else {
                    beanName = component.value();//得到自定义名称
                }
                Constructor constructor = aClass.getConstructor();//获得无参构造
                Object o = constructor.newInstance();//创建对象
                setParameter(o);//初始化参数
                objectMap.put(beanName, o);
            }
        }
        setObjectParameter(objectMap);
    }

    /**
     * 对引用的对象类型进行赋值
     */
    private void setObjectParameter(Map<String, Object> objectMap) throws IllegalAccessException {
        for (String s : objectMap.keySet()) {
            Class aClass = objectMap.get(s).getClass();
            Field[] fields = aClass.getDeclaredFields();
            for (Field field : fields) {
                if (field.isAnnotationPresent(Autowared.class)) {
                    Autowared autowared = field.getAnnotation(Autowared.class);
                    String value = autowared.value();
                    field.setAccessible(true);
                    if (value.equals("")){
                        for (String bean : objectMap.keySet()) {
                            if (field.getType().isAssignableFrom(objectMap.get(bean).getClass())
                                    ||objectMap.get(bean).getClass().isAssignableFrom(field.getType())){
                                field.set(objectMap.get(s),objectMap.get(bean));
                                break;
                            }
                        }
                    }else{
                        field.set(objectMap.get(s),objectMap.get(value));
                    }
                }
            }
        }
    }
    /**
     * 注入注解的值
     */
    public void setParameter(Object o) throws IllegalAccessException {
        for (Field field : o.getClass().getDeclaredFields()) {
            if (field.isAnnotationPresent(Value.class)) {
                Value value = field.getAnnotation(Value.class);
                String value1 = value.value();
                field.setAccessible(true);
                if (isPrimitive(field)) {
                    setPrimitive(o, value1, field);
                } else {
                    field.set(o, value1);
                }
            }
        }
    }

    /**
     * 配置基本数据类型
     */
    private void setPrimitive(Object o, String value1, Field field) throws IllegalAccessException {
        if (field.getType().isAssignableFrom(int.class) || field.getType().isAssignableFrom(Integer.class)) {
            field.set(o, Integer.parseInt(value1));
        }else if (field.getType().isAssignableFrom(short.class) || field.getType().isAssignableFrom(Short.class)){
            field.set(o, Short.parseShort(value1));
        }else if (field.getType().isAssignableFrom(long.class) || field.getType().isAssignableFrom(Long.class)){
            field.set(o,Long.parseLong(value1));
        }else if (field.getType().isAssignableFrom(char.class)) {
            field.set(o, value1.charAt(0));
        }else if (field.getType().isAssignableFrom(byte.class) || field.getType().isAssignableFrom(Byte.class)){
            field.set(o,Byte.parseByte(value1));
        }else if (field.getType().isAssignableFrom(Boolean.class) || field.getType().isAssignableFrom(boolean.class)) {
            field.set(o, Boolean.parseBoolean(value1));
        } else if (field.getType().isAssignableFrom(float.class) || field.getType().isAssignableFrom(Float.class)) {
            field.set(o,Float.parseFloat(value1));
        } else if (field.getType().isAssignableFrom(double.class) || field.getType().isAssignableFrom(Double.class)) {
            field.set(o,Long.parseLong(value1));
        }
    }

    /**
     * 判断属性的类型是否为基本类型
     */
    private boolean isPrimitive(Field value) {
        if (value.getType().isPrimitive()) {
            return true;
        }
        return false;
    }
}

ScanPackagePath类,扫描包路径


public class ScanPackagePath {


    /**
     *扫描启动类的包路径
     */
    public List<Class> scanPackagerPath(Class cls) throws ClassNotFoundException, FileNotFoundException {
        String path = cls.getClassLoader().getResource("").getPath();
        String path1 = cls.getPackageName();
        if (isOnePath(cls)) {//判断是否为同一个路径
            return getClassList(path, path1);
        } else {
            List<Class> list = null;
            if (cls.isAnnotationPresent(ComponentScanPackage.class)) {
                ComponentScanPackage clsAnnotation = (ComponentScanPackage) cls.getAnnotation(ComponentScanPackage.class);
                String value = clsAnnotation.value();
                list = getClassList(path, value);
            }
            List<Class> list1 = getClassList(path, path1);
            for (Class aClass : list1) {
                list.add(aClass);
            }
            return list;
        }
    }

    /**
     * 判断是否是同一路径
     */
    private boolean isOnePath(Class cls) {
        if (cls.isAnnotationPresent(ComponentScanPackage.class)) {
            ComponentScanPackage clsAnnotation = (ComponentScanPackage) cls.getAnnotation(ComponentScanPackage.class);
            String path1 = clsAnnotation.value();
            String path2 = cls.getPackageName();
            if (path1.equals(path2) || path2.equals("") || path1.contains(path2) || path2.contains(path1)) {
                return true;
            } else {
                return false;
            }
        }
        return true;
    }

    /**
     *获得Class集合
     */
    private List<Class> getClassList(String classPath, String packageName) throws ClassNotFoundException, FileNotFoundException {
        List<Class> list = new ArrayList<>();
        String replace = packageName.replace(".", File.separator);
        File file = new File(classPath, replace);
        File file1 = new File(classPath);
        if (!file.exists()) {
            throw new FileNotFoundException(packageName + "不存在");
        }
        getClassObject(file,file1.getPath(), list);
        return list;
    }

    /**
     *获得Class类对象
     */
    private void getClassObject(File file,String classPath, List<Class> list) throws ClassNotFoundException {
        File[] files = file.listFiles();
        for (File cls : files) {
            if (cls.isDirectory()) {
                getClassObject(cls,classPath, list);
            } else {
                if (cls.isFile()) {
                    if (cls.getName().endsWith(".class")) {
                        String clsPath = cls.getPath();
                        Class aClass = createClass(clsPath,classPath);
                        if (aClass != null) {
                            list.add(aClass);
                        }
                    }
                }
            }
        }
    }

    /**
     * 创建对象
     */
    private Class createClass(String classPath, String path) throws ClassNotFoundException {
    //获得类的全限定类名
        String cls = classPath.substring(path.length()+1,classPath.length()-6).replace(File.separator,".");
        Class aClass = Class.forName(cls);
        return (aClass.isInterface()||aClass.isAnnotation())?null:aClass;
    }
}

容器ApplicationContext父接口

public interface ApplicationContext {

    Object getBean(String name) throws ClassNotFoundException;
    <T> T getBean(String name,Class cls)throws ClassNotFoundException;
    Integer getBeanSize();
    List<Object> getBeanList();

}

ApplicationContextBeanFactory二级接口(这里设计的不好,可以合并到ApplicationContext)

public interface ApplicationContextBeanFactory extends ApplicationContext {

    List<Class> getClassList(Class cls) throws ClassNotFoundException, FileNotFoundException;

    Map<String,Object> createObject() throws InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException;
}

ApplicationContextBeanFactory的实现类ApplicationContextAnnotationBeanFactory

public class ApplicationContextAnnotationBeanFactory implements ApplicationContextBeanFactory {

    private Map<String, Object> objectMap;
    private List<Class> classList;

    public ApplicationContextAnnotationBeanFactory(Class cls) throws Exception {
        if (!cls.isAnnotationPresent(AnnotationBootStrap.class)) {
            throw new RuntimeException(cls+"不是一个启动类,没有AnnotationBootStrap注解");
        } else {
            AnnotationBootStrap bootStrap = (AnnotationBootStrap) cls.getAnnotation(AnnotationBootStrap.class);
            if (bootStrap.value()) {
                this.classList = getClassList(cls);
                objectMap = createObject();
            } else {
                throw new RuntimeException("AnnotationBootStrap启动类没有开启:false");
            }
        }
    }

    @Override
    public Object getBean(String name) throws ClassNotFoundException {
        return objectMap.get(name);
    }

    @Override
    public <T> T getBean(String name, Class cls) throws ClassNotFoundException {
        return (T) objectMap.get(name);
    }


    @Override
    public Integer getBeanSize() {
        return objectMap.size();
    }
    @Override
    public List<Object> getBeanList() {
        List<Object> list = new ArrayList<>();
        for (String beanName : objectMap.keySet()) {
            list.add(objectMap.get(beanName));
        }
        return list;
    }
    @Override
    public List<Class> getClassList(Class cls) throws ClassNotFoundException, FileNotFoundException {
        return new ScanPackagePath().scanPackagerPath(cls);
    }

    @Override
    public Map<String, Object> createObject() throws InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException {
        CreateFactoryBean createFactoryBean = new CreateFactoryBean();
        objectMap = createFactoryBean.getNoConstructor(classList);
        return objectMap;
    }
}

启动类

@AnnotationBootStrap//声明该类为启动类(默认为true,false表示不启动该功能)
@ComponentScanPackage("cn.edu.mapper")//扫描包(可以不声明,默认使用该类的包路径)
public class MyTestAnnotation {

    public static void main(String[] args) throws Exception {
        ApplicationContext app = new ApplicationContextAnnotationBeanFactory(MyTestAnnotation.class);
        User user = (User) app.getBean("user");
        System.out.println(user);
    }
}

实体类

@Component("test")
public class Test {
    @Value("杨万里")
    private String name;

    public void print(){
        System.out.println("Hello,I am advance notice");
    }
    @Override
    public String toString() {
        return "Test{" +
                "name='" + name + '\'' +
                '}';
    }
}

@Component("user")
public class User {

    @Value("貂蝉")
    private String name;
    @Value("女")
    private String sex;
    @Value("3")
    private int age;
    @Autowared
    private Test test;

    public User() {
    }

    public User(String name, String sex, int age, Test test) {
        this.name = name;
        this.sex = sex;
        this.age = age;
        this.test = test;
    }
    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", age=" + age +
                ", test=" + test +
                '}';
    }
}

运行结果
在这里插入图片描述
在写这个IOC的时候,边写边想,所有在设计上思路并没有太清晰,整体上存在一些缺陷,请见谅。各位在参考这篇文章的时候,可以结合JDK动态代理和Cglib,参考Spring的基本原理可以达到更好的效果(此处没有对接口进行管理)。注意哦:private修饰的属性和方法注解类不能被继承,Spring中条件注解Condidtion条件注解是一个很好的参考源码地址,Gitee

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java反射机制是指在程序运行时动态地获取一个类的信息,包括类的属性、方法和构造函数等,并能够在运行时调用这些属性和方法,而不需要事先知道这个类的具体信息。Java反射机制实现框架(如Spring)的基础,它使得我们可以在不修改原有代码的情况下,动态地创建对象、调用方法、获取属性等操作,从而实现程序的灵活性和扩展性。 Java反射机制的核心是Class类,每个类都有一个对应的Class对象,它包含了该类的所有信息,包括类名、方法、属性等。通过Class对象可以获取类的信息,并对类进行操作。 Java IOC(Inversion of Control,控制反转)是一种设计模式,它将对象的创建、管理、依赖关系的维护等工作交给容器来完成,从而实现了组件之间的松耦合和可重用性。Java IOC的核心是容器容器负责管理各个组件之间的依赖关系,并在需要的时候动态地创建和注入对象。 Java IOC实现依赖于反射机制容器通过反射机制获取类的信息,并通过构造函数或setter方法来创建和注入对象。Java IOC的好处是可以将各个组件解耦,使得程序更加灵活和可扩展,同时也提高了代码的可测试性和可维护性。 综上所述,Java反射机制实现Java IOC的基础,Java IOC利用反射机制实现对象的动态创建和注入。反射机制IOC的合理运用可以使程序更加灵活和可扩展。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值