Spring Spring Ioc

166 阅读4分钟

大明王朝里面提到了三思这个词的解释,三思就是思危,思退,思变,也就是思考所处的危险,自己不对的地方,然后退到一个安全的地方,然后改变自己,从而争取到更好的机会,最重要的是一个思字,很多事情没有思考,那就是高屋建瓴,基础不牢,地动山摇,这也是为什么,编程要学习算法,要学习源码。

现在来说说,我们最熟悉的Spring Ioc

说是熟悉,但我总觉得,他是一个最熟悉的陌生人,为什么这么说呢,因为我们可能就是在调用他的API而已。

说他之前,先说说Spring的组成

image.png

1 核心Core 他主要是由BeanFactory来构成的

2 上下文Context 这个我们应该熟悉,加载配置文件之后,解析成的各种ApplicationContext就是他了。

3 Spring Dao 是一个抽象层,如果数据库方面报错抛异常主要由他管理

4 Spring Aop 这个应该都知道

5 Spring web 也不说了

这个是Spring的架构,具体就不讲了。

从里面看Spring是非常大的,包罗万象。

于是,他就有了一个缺点,是啥呢?

1 重量级框架

他太大了,什么都有,即便我用不到的也有,我之前写JPA的时候,他的设计是,有一个标识作用的接口Resiposity,然后有三个接口分别继承他,每一个继承上一个,这样最后一个的功能就最强大,那么问题来了,既然最后一个最强大,那我用最后一个不就可以了,那前面的还有什么存在的必要,表面上看是这样的,但是功能强大的也有其负面,就是加载的东西太多了,会消耗更多的内存,所以这反而是一个缺点

2 学习难度大

Spring的源码体系太过庞大,一个上下文就好多类,而且为了代码及其灵活,使用很多的设计模式导致代码的可读性发生下降,学习成本变得更高,当然,如果知识想调用Api接口那就没事了,但是,做技术的要有最技术的追求,还是要对其学习

3 配置复杂

现在很多项目还是使用xml的形式配置,就导致配置的成本变的比较高

回归正题,Spring Ioc到底是啥? 我想只要学过java的都会说,控制反转,依赖注入。

那啥是控制反转,啥又是依赖注入,他又是怎么实现的。

那很多人就会说,控制反转就是控制权交给Spring管理,而不是自己管理。再具体点呢,是什么控制权给了Spring,我想很多人就会答不上来了。

来看下代码

@Service
public class SpringDemo
{
    @Autowired
    private ScheduleJob scheduleJob;

    public void test(){
        scheduleJob.cronTask();
    }
}

这段代码,如果没有通过Spring的@Autowired那会怎么样呢,那他就是会报错的,为什么呢,因为对象是null的,我们知道jvm是要对象实例话之后才会在堆中给对象分配内存空间,才能调用对象中的方法,因为是null所以,调用不了,当然就报错啦。

那用上了@Autowired为什么就不报错了呢,其实这个就是我们说的控制反转,加上了@AutoWired就是从Spring的BeanFactory 中取值,而BeanFactory 中存储了已经实例化好的对象,这个对象是Spring帮助我们实例化的。而Spring容器帮我们实例化而不是我们手动实例化,这个就是控制反转了,控制就体现在对象的实例化上,之前使我们自己写代码手动实例,现在我们可以歇菜了,Spring帮我们实例化,这样就很清晰了。

那他是怎么帮我们实例化的呢,这个就离不开我们的核心BeanFactory了也就是Bean工厂,我们看看他有那些实现

image.png

public interface BeanFactory {
    String FACTORY_BEAN_PREFIX = "&";

    Object getBean(String var1) throws BeansException;

    <T> T getBean(String var1, Class<T> var2) throws BeansException;

    Object getBean(String var1, Object... var2) throws BeansException;

    <T> T getBean(Class<T> var1) throws BeansException;

    <T> T getBean(Class<T> var1, Object... var2) throws BeansException;

    boolean containsBean(String var1);

    boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;

    boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException;

    Class<?> getType(String var1) throws NoSuchBeanDefinitionException;

    String[] getAliases(String var1);
}

他长这样,这个就是Spring的核心,Spring是喜欢谁就Bean谁,我们所有的对象最终都会放到他里面去,然后读取的时候,再从他里面拿,但是并不是直接从它里面拿,一般我们都是通过Context上下文里面拿,因为上下文包含他。怎么包含的

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
  String getId();

    String getApplicationName();

    String getDisplayName();

    long getStartupDate();

    ApplicationContext getParent();

    AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
}

我们看到这里面有一个

AutowireCapableBeanFactory 然后看看他,他继承了Bean工厂

public interface AutowireCapableBeanFactory extends BeanFactory {
    int AUTOWIRE_NO = 0;
    int AUTOWIRE_BY_NAME = 1;
    int AUTOWIRE_BY_TYPE = 2;
    int AUTOWIRE_CONSTRUCTOR = 3;
    -----------
}

所以我们一般看到的都是这种

ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");

ClassName clazz =(ClassName)ctx.getBean("beanName");

而上下文就是通过配置文件获取的了,这就是SpringIoc的简单的叙述。