今天给大家分享一下,修真院官网JAVA任务一,深度思考中的知识点——Spring中的IOC是什么意思,为什么要用IOC而不是New来创建实例?
一、背景介绍
Spring是一个开源的轻量级Java SE(Java 标准版本)/Java EE(Java 企业版本)开发应用框架,其目的是用于简化企业级应用程序开发。应用程序是由一组相互协作的对象组成。而在传统应用程序开发中,一个完整的应用是由一组相互协作的对象组成。所以开发一个应用除了要开发业务逻辑之外,最多的是关注如何使这些对象协作来完成所需功能,而且要低耦合、高内聚。业务逻辑开发是不可避免的,那如果有个框架出来帮我们来创建对象及管理这些对象之间的依赖关系。可能有人说了,比如“抽象工厂、工厂方法设计模式”不也可以帮我们创建对象,“生成器模式”帮我们处理对象间的依赖关系,不也能完成这些功能吗?可是这些又需要我们创建另一些工厂类、生成器类,我们又要而外管理这些类,增加了我们的负担,如果能有种通过配置方式来创建对象,管理对象之间依赖关系,我们不需要通过工厂和生成器来创建及管理对象之间的依赖关系,这样我们是不是减少了许多工作,加速了开发,能节省出很多时间来干其他事。Spring框架刚出来时主要就是来完成这个功能。Spring框架除了帮我们管理对象及其依赖关系,还提供像通用日志记录、性能统计、安全控制、异常处理等面向切面的能力,还能帮我管理最头疼的数据库事务,本身提供了一套简单的JDBC访问实现,提供与第三方数据访问框架集成(如Hibernate、JPA),与各种Java EE技术整合(如Java Mail、任务调度等等),提供一套自己的web层框架Spring MVC、而且还能非常简单的与第三方web框架集成。从这里我们可以认为Spring是一个超级粘合平台,除了自己提供功能外,还提供粘合其他技术和框架的能力,从而使我们可以更自由的选择到底使用什么技术进行开发。
二、知识剖析
1、IoC是什么?
IoC容器就是具有依赖注入功能的容器
BeanFactory提供了IoC容器最基本功能,而 ApplicationContext 则增加了更多支持企业级功能支持。ApplicationContext完全继承BeanFactory,因而BeanFactory所具有的语义也适用于ApplicationContext。
2、bean
由IoC容器管理的那些组成你应用程序的对象我们就叫它Bean, Bean就是由Spring容器初始化、装配及管理的对象,除此之外,bean就与应用程序中的其他对象没有什么区别了。
Bean命名约定:Bean的命名遵循XML命名规范,但最好符合Java命名规范,由“字母、数字、下划线组成“,而且应该养成一个良好的命名习惯, 比如采用“驼峰式”,即第一个单词首字母开始,从第二个单词开始首字母大写开始,这样可以增加可读性。
3、两种配置方式去理解IOC和DI
xml方式配置:bean的装配、之间的依赖关系放在xml配置文件中;修改依赖关系时,更改xml文件更简便;更容易理解IOC的思想,强调通过spring来实例化对象,存于容器中去进行管理
Annotation注解的方式:配置起来更简单,节省部分代码;修改时不方便;依赖关系不直观;更容易理解DI的实现,强调注入的过程
IoC容器就是具有依赖注入功能的容器
BeanFactory提供了IoC容器最基本功能,而 ApplicationContext 则增加了更多支持企业级功能支持。ApplicationContext完全继承BeanFactory,因而BeanFactory所具有的语义也适用于ApplicationContext。
2、bean
由IoC容器管理的那些组成你应用程序的对象我们就叫它Bean, Bean就是由Spring容器初始化、装配及管理的对象,除此之外,bean就与应用程序中的其他对象没有什么区别了。
Bean命名约定:Bean的命名遵循XML命名规范,但最好符合Java命名规范,由“字母、数字、下划线组成“,而且应该养成一个良好的命名习惯, 比如采用“驼峰式”,即第一个单词首字母开始,从第二个单词开始首字母大写开始,这样可以增加可读性。
3、两种配置方式去理解IOC和DI
xml方式配置:bean的装配、之间的依赖关系放在xml配置文件中;修改依赖关系时,更改xml文件更简便;更容易理解IOC的思想,强调通过spring来实例化对象,存于容器中去进行管理
Annotation注解的方式:配置起来更简单,节省部分代码;修改时不方便;依赖关系不直观;更容易理解DI的实现,强调注入的过程
即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。
传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对象的创建
三、常见问题
1、什么是Bean?
2、为什么要用IOC而不是New来创建实例?
四、解决方案
1、由IoC容器管理的那些组成你应用程序的对象我们就叫它Bean, Bean就是由Spring容器初始化、装配及管理的对象,除此之外,bean就与应用程序中的其他对象没有什么区别了。2、为什么要用IOC而不是New来创建实例?
查阅资料遇到的观点:
(1)底层类构造方法改变、后续代码改动较大
采用有参的构造方法,增减构造方法的参数,会对后续的类中都产生影响。
但是无参的构造方法,通过setter方法注入属性参数和spring的改动是相同的,也就是说不是为了减少代码,资料的目的在于帮助我们理解由上层依赖下层转变为依赖spring容器这一概念;
原因:
spring方式bean实例化的本质:SpringContext利用无参的构造函数创建一个对象,然后利用setter方法赋值。
Ps:如果无参构造函数不存在,Spring上下文创建对象的时候便会报错
(2)比如你有一个A类 在好几个类里边要调用到A的方法 new的话就要在每个类里都new A(); spring的话 只要配置一个bean进行注入就够了。 哪天你不用A类了 改成B了~ 直接把bean里边的class改成B就搞定了 如果用new的话 要改好几个地方。
为什么写的这些简单代码,体现不出优点,
不是更换一个实体类时,而是当我们更换一个实现子类将会变得很简单,只要修改配置文件就可以了
spring注入真正体现了对象编程的思想,只要注入对象的创建就由spring管理,直接使用就可以了,new对象你得知道具体的实现类
spring ioc容器中相当于通过无参的构造方法实例化bean,本质上还是new了一个对象, 实例化之后存储在内存之中:
JdbcTemplate jdbcTemplate = new JdbcTemplate();
UserDao userDao = new UserDaoImpl();
UserService userService = new UserService();
五、编码实战
基于以上三个观点的尝试六、扩展思考
1、单例模式和多例模式
多例模式是为了防止一个请求改变了对象的状态,此时对象又处理另一个请求,而之前请求对对象的状态改变导致了对象对另一个请求做了错误的处理;service和dao整个系统的一个模块只需要一个,而且只调用这些类的方法,请求一般不会改变对象的状态
2、Spring中实体类为什么不需要注册成bean?
比如一个User实体类,它只是个POJO,是个存放数据的载体。spring处理那些“为了使用该类方法”的类,而实体类是为了存储数据。
七、参考文献
https://blog.csdn.net/mr_gent/article/details/54666560https://blog.csdn.net/weixin_40423553/article/details/80061881
https://blog.csdn.net/likunyv/article/details/79291474
https://www.cnblogs.com/liangyihui/p/5917773.html
https://www.cnblogs.com/kenshinobiy/p/4652008.html
八、更多讨论
1、Spring上下文Bean的生命周期?Spring上下文中的Bean也类似,如下
1、Spring对bean进行实例化,默认bean是单例;
2、Spring对bean进行依赖注入;
3、如果这个Bean已经实现了BeanNameAware接口,会调用它实现的setBeanName(String)方法,此处传递的就是Spring配置文件中Bean的id值
4、如果这个Bean已经实现了BeanFactoryAware接口,会调用它实现的
setBeanFactory(setBeanFactory(BeanFactory)传递的是Spring工厂自身(可以用这个方式来获取其它Bean,只需在Spring配置文件中配置一个普通的Bean就可以);
5、如果这个Bean已经实现了ApplicationContextAware接口,会调用setApplicationContext
(ApplicationContext)方法,传入Spring上下文(同样这个方式也可以实现步骤4的内容,但比4更好,因为ApplicationContext是BeanFactory的子接口,有更多的实现方法);
6、如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessBeforeInitialization(Object obj, String s)方法,BeanPostProcessor经常被用作是Bean内容的更改,并且由于这个是在Bean初始化结束时调用那个的方法,也可以被应用于内存或缓存技术;7、如果Bean在Spring配置文件中配置了init-method属性会自动调用其配置的初始化方法。
8、如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessAfterInitialization(Object obj, String s)方法、;
注:以上工作完成以后就可以应用这个Bean了,那这个Bean是一个Singleton的,所以一般情况下我们调用同一个id的Bean会是在内容地址相同的实例,当然在Spring配置文件中也可以配置非Singleton,这里我们不做赘述。
9、当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,会调用那个其实现的destroy()方法;
10、最后,如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法。
2、单例模式和多例模式的配置形式?
在Spring中,bean可以被定义为两种模式:prototype(多例)和singleton(单例)
singleton(单例):只有一个共享的实例存在,所有对这个bean的请求都会返回这个唯一的实例。
prototype(多例):对这个bean的每次请求都会创建一个新的bean实例,类似于new。
Spring bean 默认是单例模式。
XML文件中,
<bean id="userMapper2" class="com.mapper.UserMapper" scope="prototype"></bean>
注解方式,在注解下加上@Scope("prototype")
3、请解释下Spring框架中的IoC?
Spring中的 org.springframework.beans 包和 org.springframework.context包构成了Spring框架IoC容器的基础。BeanFactory 接口提供了一个先进的配置机制,使得任何类型的对象的配置成为可能。ApplicationContex接口对BeanFactory(是一个子接口)进行了扩展,在BeanFactory的基础上添加了其他功能,比如与Spring的AOP更容易集成,也提供了处理message resource的机制(用于国际化)、事件传播以及应用层的特别配置,比如针对Web应用的WebApplicationContext。
org.springframework.beans.factory.BeanFactory 是Spring IoC容器的具体实现,用来包装和管理前面提到的各种bean。BeanFactory接口是Spring IoC 容器的核心接口。
感谢观看,如有出错,恳请指正