【反射】(03)反射之工厂设计模式(浅谈Spring实现IOC)

(1)工厂模式简要分析

(1.1)先来认识Spring中的IOC功能(以下内容纯属我自己的猜测)

(1.1.1)我的猜测

在spring框架中实现了IOC的容器,作用就是把所有的类对象看做是Bean,然后放进IOC容器里进行管理,当你想用到这个对象时,不再需要new来实例化对象,而是直接从IOC容器中取出已经实例化的对象。

既然IOC容器帮我们完成了实例化对象,肯定不是它自己偷偷摸摸的用new关键字实例化了对象,我们的目标就是尽量少用new关键字来降低耦合度,那么它是怎么帮我们完成对象实例化的工作呢?

经过反射的深入学习后,我知道可以根据一个类的路径(包名.类名)反向获取到这个类,那么我们把这个路径交给IOC容器,此时IOC容器已经反射得到这个类了。经过反射的深入学习,我们又知道反射的一项重要功能就是可以用Class类调用构造方法实例化对象。

那么我们就明白了,对象Bean交个IOC容器后,IOC使用反射,显示创建Class对象,然后用Class类对象调用构造方法实例化对象,完全不用new关键字。实例化的对象就在容器中管理,想用你就直接来拿吧。

(1.1.2)总结一下:Spring的IOC用的技术有两点

1)你把类的路径给我,我能根据这个路径反向获取你这个类
2)有了这个类,我再用Class类来实例化这个类的对象,并把对象返回给你

(1.1.3)来看看实际应用中IOC容器是怎么实现DI依赖注入的:

1)在类的上方加注解,这个注解就把这个类的路径传给IOC容器了
在这里插入图片描述
IOC获取到路径以后就要开始一系列的骚操作了,原理代码如下:

        Class<?> clazz=null;
        String path="注解@Mapper传进来的类路径";
        //Class对象实例化,反射声明RealSubject类对象
        try {
            //实例化Class类对象最常用的形式
            clazz=Class.forName(path);
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

现在还没有实例化对象,我们接着往下走

2)当你要用到这个对象时,你会先声明对象,并在这个对象上加上注解
在这里插入图片描述
加上注解后,就等于通知IOC容器,老哥,我现在急用对象,赶紧实例化一个对象给我用用。于是IOC开始如下的骚操作,原理代码如下:

        //声明RealSubject类对象
        CategoryMapper categoryMapper= null;
        //Class类对象调用newInstance方法,等于调用RealSubject构造方法来对象实例化
        try {
            //Java9之后,newInstance方法已经被弃用,改用:getDeclaredConstructor().newInstance()
            categoryMapper= (CategoryMapper ) clazz.getDeclaredConstructor().newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

此时你声明的对象已经被Class类用“clazz.getDeclaredConstructor().newInstance();”这串代码调用构造器实例化好了,一眨眼的功夫,你的对象categoryMapper 已经被实例化了。你可以开始愉快的调用了

(1.2)实现一个简单的工厂设计模式

(1.2.1)第一步:实现一个接口Fruit,统一管理子类
public interface Fruit {
    public void eat();
}
(1.2.2)第二步:实现两个接口的子类
public class Orange implements Fruit {
    @Override
    public void eat() {
        System.out.println("吃橘子");
    }
}

public class Apple implements Fruit {
    @Override
    public void eat() {
        System.out.println("吃苹果");
    }
}
(1.2.3)实现一个工厂(类似于IOC容器)

上面说的,Spring中是使用注解@Mapper把路径传给容器的,我们这里手动传路径,把路径当做参数className传给方法getInsance,这个方法专门用反射实例化对象,有了路径一切就都好说了,瞧好吧您

public class Factory {
    public static Fruit getInsance(String className){
        Fruit fruit = null;
        try {
            fruit = (Fruit) Class.forName(className).getDeclaredConstructor().newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        return fruit;
    }
}
(1.2.3)测试类

上面我们说了,getInstance方法就是专门用反射根据路径实例化对象的,现在我们声明对象,然后把子类的路径当做参数className传给方法,方法内部就会实例化对象,并且返回一个已经实例化的对象,我们再把这个对象向上转型成Fruit类型

public class FactoryDemo {
    public static void main(String[] args) {
        Fruit apple = Factory.getInsance("part03_工厂模式.p05_反射之工厂设计模式.Apple");
        apple.eat();
        Fruit orange = Factory.getInsance("part03_工厂模式.p05_反射之工厂设计模式.Orange");
        orange.eat();
    }
}

我们用上面方法返回的对象调用类的方法,看看它是不是真的已经实例化了,运行结果如下
在这里插入图片描述

果然,这个对象已经完成实例化了,仔细看,我们从头到尾都没有使用new,这就是我们追求的效果。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值