(001)Spring 之 IOC及其容器
概述
Spring的最终模板是简化应用开发的编程模型。spring用于替代更加重量级的企业级java技术,如EJB(Enterprise JavaBean)。
为了降低Java开发的复杂度。spring采取了以下4中关键策略:
- 基于POJO(Plain Ordinary Java Objects,实际上就是普通的java类)的轻量级和最小侵入式编程。
- 通过依赖注入(DI, Dependency Injection)和面向接口编程实现松耦合。
- 基于切面(AOP, Aspect Oriented Programming)和惯例(可以理解为默认配置、方式)进行声明式编程。
- 通过切面和模板减少重复代码。
他山之石
- 谈谈对Spring IOC的理解:blog.csdn.net/qq_22654611…
- 长话短说Spring(1)之IoC控制反转:www.jianshu.com/p/dff5484f4…
- Spring IOC原理总结:www.jianshu.com/p/6253726f2…
- Spring IoC有什么好处呢?:www.zhihu.com/question/23…
- Spring实现IoC的多种方式:www.cnblogs.com/best/p/5727…
- Spring容器初始化过程:www.cnblogs.com/luyanliang/…
IOC容器存在价值
Java是一门面向对象编程语言。Java应用本质上是一个个对象及其关系的组合。举个简单的例子。
在传统的人员招聘模式中,流程一般都是这样:HR从多如海的应聘简历中挑选然后进行笔试、面试等等一系列筛选后发放offer。这一系列过程复杂而且费时,最关键的是结果还不理想,特别是针对某些特定的岗位很难通过这一模式物色到合适的人才资源。 (自己创建特定的对象,使用特定的对象)
后来逐渐出现了一些公司专门提供类似的人才寻访服务,这就是大名鼎鼎的猎头行业。猎头的兴起可以说很大程度上改变了人才招聘的模式,现在公司需要招聘某个职位的人才,只需要告诉猎头我要一个怎样的人干怎样的工作等等要求,猎头就会通过自己的渠道去物色人才,经过筛选后提供给客户,大大简化了招聘过程的繁琐,提高了招聘的质量和效率。(告诉中间人,中间人自动给你需要、合适的对象)
这其中一个很重要的变化就是公司HR将繁琐的招聘寻访人才的过程转移至了第三方,也就是猎头。相对比而言,IoC在这里充当了猎头的角色,开发者即公司HR,而对象的控制权就相当于人才寻访过程中的一系列工作。
一句话,在java中,将对象的创建与对象的使用分离开,通过依赖注入(DI)的方式达到对象控制反转(IOC)的目的。原本需要自己做创建对象、维护各个对象关系,现在统一交给统一专业的人或服务处理。
创建对象等操作就是你对对象的控制权,把控制权交给三方,这就是 控制反转(IOC) 的意思。
当需要某个对象的时候,三方将合适的对象给你,这个就是 依赖注入(DI) 的意思。
关系
主要类或接口uml图
ApplicationContext 扩展了BeanFactory后的结果,BeanFactory为bean对象的出生地。
BeanDefinition载入
定义一个bean对象长什么样子,在spring中叫BeanDefinition。如何初始化一个BeanDefinition,spring中常用三种方式定义:xml文件、注解扫描、java代码.
bean的生命周期
Bean的完整生命周期经历了各种方法调用,这些方法可以划分为以下几类:
- Bean自身的方法:这个包括了Bean本身调用的方法和通过配置文件中的init-method和destroy-method指定的方法。
- Bean级生命周期接口方法:这个包括了BeanNameAware、BeanFactoryAware、InitializingBean和DisposableBean这些接口的方法
- 容器级生命周期接口方法:这个包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为“后处理器”。
- 工厂后处理器接口方法:这个包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工厂后处理器接口的方法。工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用。
举例(通过注解与java代码定义bean)
- 定义一个Animal接口。
- 定义实现Animal接口的两个动物Cat,Dog类;
- 定义一个接口代理AnimalProxy。
- 定义一个spring Bean java类
实现通过代理类完成不同操作。
1.Animal接口
package bean; public interface Animal { public void sayName(); }
2.Cat类
package bean; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; @Primary @Component public class Cat implements Animal { public void sayName() { System.out.println("this is cat"); } }
3.Dog类
package bean; import org.springframework.stereotype.Component; @Component public class Dog implements Animal { public void sayName() { System.out.println("this is dog"); } }
4.AnimalProxy类
package bean; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class AnimalProxy implements Animal { @Autowired private Animal animal; public void sayName(){ animal.sayName(); } }
5. AnimalConfig(Bean定义类)
package bean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; /** * User: Rudy Tan * Date: 2017/11/24 */ @Configuration @ComponentScan @EnableAspectJAutoProxy(proxyTargetClass = true) public class AnimalConfig { }
6.测试类:
import bean.*; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = AnimalConfig.class) public class AppTest { @Autowired private AnimalProxy animalProxy; @Test public void testBeanLoad(){ animalProxy.sayName(); } }
说明:
- 注解Component:指明该类为bean类
- 注解Primary:指明当多个bean对象满足获取条件时候,该对象优选获取。
- 注解Configuration:指明该类为spring bean定义类。
- 注解ComponentScan:开启当前目录下的bean注解扫描。
- 注解EnableAspectJAutoProxy:启用aspectJauto代理。
- 注解Autowired:该属性,spring自动载入。
总结,多人个人或多个类协助处理问题或实现某个功能,总得要找个领头的来管理这些关系吧。