1.Spring IoC源码深度剖析
2.Spring源码- 02 Spring IoC容器启动之refresh方法
3.Spring IoC:getBean 详解
4.springçç»ä»¶åä½ç¨(springclouç»ä»¶)
5.如何快速读懂项目源码javaWeb
6.IOCåAOPçåºå«ï¼
Spring IoC源码深度剖析
Spring IoC容器初始化深度剖析
Spring IoC容器是码设Spring的核心组件,主要负责对象管理和依赖关系管理。码设容器体系丰富多样,码设如BeanFactory作为顶层容器,码设它定义了所有IoC容器的码设基本原则,而ApplicationContext及其子类如ClassPathXmlApplicationContext和AnnotationConfigApplicationContext则提供了额外功能。码设放量打拐指标源码Spring IoC容器的码设初始化流程关键在AbstractApplicationContext的refresh方法中。 1.1 初始化关键点 通过创建特定类LagouBean并设置断点,码设我们发现Bean的码设创建在未设置延迟加载时,发生在容器初始化过程中。码设构造函数调用、码设InitializingBean的码设afterPropertiesSet方法以及BeanFactoryPostProcessor和BeanPostProcessor的初始化和调用,都在refresh方法的码设不同步骤中发生。 1.2 主体流程概览 Spring IoC容器初始化的码设主体流程主要集中在AbstractApplicationContext的refresh方法,涉及Bean对象创建、码设构造函数调用、初始化方法执行和处理器调用等步骤。 1.3 深度剖析 分析发现,延迟加载机制使得懒加载的bean在第一次调用getBean时才进行初始化。而对于非懒加载bean,它们在容器初始化阶段已经完成并缓存。Spring处理循环依赖的方法依赖于构造器调用的顺序规则,不支持原型bean的循环依赖,而对单例bean则通过setXxx或@Autowired方法提前暴露对象来避免循环依赖。Spring源码- Spring IoC容器启动之refresh方法
在注册阶段,AnnotationConfigApplicationContext构造方法中的第一个方法被分析过。接下来,我们关注第二个方法:register(componentClasses)。在使用XML配置方式时,rpg安卓游戏源码通过new ClassPathXmlApplicationContext("classpath:spring.xml")来创建实例,其中需要指定xml配置文件路径。使用注解方式时,也需要为ApplicationContext提供起始配置源头,这里使用配置类代替xml配置文件,按照配置类中的注解(如@ComponentScan、@Import、@Bean)解析并注入Bean到IoC容器。
通过配置类,Spring解析注解实现Bean的注入。使用@Configuration注解定义的配置类相当于xml配置文件,但目前Spring推荐使用注解方式,xml配置的使用概率正在降低。
register(componentClasses)方法的核心逻辑在AnnotatedBeanDefinitionReader#doRegisterBean中,将传入的配置类解析为BeanDefinition并注册到IoC容器。ConfigurationClassPostProcessor这个BeanFactory后置处理器在IoC初始化时,获取配置类的BeanDefinition集合,开始解析。
真正启动IoC容器的流程在refresh()方法中,这是了解IoC容器启动流程的关键步骤。refresh方法在AbstractApplicationContext中定义,采用模板模式,提供IoC初始化流程的基本实现,子类可以扩展。
下面分析refresh()方法的每个步骤,以了解IoC容器的启动流程。
prepareRefresh方法主要在refresh执行前进行准备工作,如设置Context的注册登录模板源码下载启动时间、状态,以及扩展系统属性相关。
initPropertySources()方法主要用于扩展配置来源,如网络、物理文件、数据库等加载配置信息。StandardEnvironment默认只提供加载系统变量和应用变量的功能,用于子类扩展。
❝initPropertySources方法常见扩展场景包括:❞
getEnvironment().validateRequiredProperties()确保设置的必要属性在环境中存在,否则抛出异常终止应用。
BeanFactory是Spring的基本IoC容器,ApplicationContext包装了BeanFactory,提供更智能、更便捷的功能。ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();获取的BeanFactory是IoC容器初始化工作的基础。
上面获取的BeanFactory还不能直接使用,需要填充必要的配置信息。至此,IoC容器的启动流程基本完成。
这里对IoC启动流程有个大致、直观的印象。主要步骤包括:准备阶段、配置来源扩展、初始化BeanFactory、填充配置、解析配置类、注册Bean、实例化BeanPostProcessor、wap水果机源码初始化国际化和事件机制、以及创建内嵌Servlet容器(在SpringBoot中实现)。这些步骤确保了IoC容器顺利启动并管理Bean。
Spring IoC:getBean 详解
接着 Spring IoC:finishBeanFactoryInitialization 详解,我们正式开始学习获取 bean 实例方法,该方法是 Spring 最核心的方法。
单击 preInstantiateSingletons 方法里的 getBean(beanName) 代码,进入该方法。
见 doGetBean 方法详解。
doGetBean
1.解析 beanName,主要是解析别名、去掉 FactoryBean 的修饰符 “&”,在 Spring IoC:finishBeanFactoryInitialization 详解 中的代码块4已解析过。
2.尝试从缓存中获取 beanName 对应的实例,在 Spring IoC:finishBeanFactoryInitialization 详解 中的代码块7已解析过。
3.1 返回 beanName 对应的实例对象(主要用于 FactoryBean 的特殊处理,普通 bean 会直接返回 sharedInstance 本身),见代码块1详解。
6.如果不是仅仅做类型检测,而是创建 bean 实例,这里要将 beanName 放到 alreadyCreated 缓存,见代码块5详解。
7.根据 beanName 重新获取 MergedBeanDefinition,在 Spring IoC:finishBeanFactoryInitialization 详解 中的代码块2已解析过。
8.2 检查 dep 是否依赖于 beanName,即检查是否存在循环依赖,见代码块6详解。
8.4 将 dep 和 beanName 的android通知栏网速源码依赖关系注册到缓存中,见代码块7详解。
9.1 scope 为 singleton 的 bean 创建(新建了一个 ObjectFactory,并且重写了 getObject 方法),见代码块8详解。
9.1.1、9.2.2、9.3.4 创建 bean 实例,限于篇幅,在下篇文章单独解析。
9.1.2、9.2.4、9.3.6 返回 beanName 对应的实例对象,见代码块1详解。
9.2.1 scope 为 prototype 时创建实例前的操作、9.2.3 scope 为 prototype 时 创建实例后的操作,相对应的两个方法,见代码块详解。
代码块1:getObjectForBeanInstance
如果对 FactoryBean 不熟悉的,可以回头去看 Spring IoC:finishBeanFactoryInitialization 详解 中对 FactoryBean 的简单介绍。
6.mbd 为空,但是该 bean 的 BeanDefinition 在缓存中存在,则获取该 bean 的 MergedBeanDefinition,在 Spring IoC:finishBeanFactoryInitialization 详解 中的代码块2已经解析过。
8.从 FactoryBean 获取对象实例,见代码块2详解。
代码块2:getObjectFromFactoryBean
3.调用 FactoryBean 的 getObject 方法获取对象实例,见代码块3详解。
5.对 bean 实例进行后续处理,执行所有已注册的 BeanPostProcessor 的 postProcessAfterInitialization 方法,见代码块4详解。
代码块3:doGetObjectFromFactoryBean
很简单的方法,就是直接调用 FactoryBean 的 getObject 方法来获取到对象实例。
细心的同学可以发现,该方法是以 do 开头,看过 Spring IoC:源码总览 的同学知道,我在总览里就特别提到以 do 开头的方法是最终进行实际操作的方法,例如本方法就是 FactoryBean 最终实际进行创建 bean 对象实例的方法。
代码块4:postProcessObjectFromFactoryBean
这边走的是 AbstractAutowireCapableBeanFactory 里的方法。通过前面的介绍,我们知道创建的 BeanFactory 为 DefaultListableBeanFactory,而 DefaultListableBeanFactory 继承了 AbstractAutowireCapableBeanFactory,因此这边会走 AbstractAutowireCapableBeanFactory 的重写方法。
在 Spring IoC:registerBeanPostProcessors 详解 中已经学过 BeanPostProcessor,在创建完 bean 实例后,会执行 BeanPostProcessor 的 postProcessAfterInitialization 方法。
代码块5:markBeanAsCreated
2.这边会将 beanName 对应的 MergedBeanDefinition 移除,然后在之后的代码重新获取,主要是为了使用最新的 MergedBeanDefinition 来进行创建操作。
代码块6:isDependent
这边引入了一个缓存 dependentBeanMap:beanName -> 所有依赖 beanName 对应的 bean 的 beanName 集合。内容比较简单,就是检查依赖 beanName 的集合中是否包含 dependentBeanName,隔层依赖也算。例如:A 依赖了 B,B 依赖了 C,则 A 也算依赖了 C。
代码块7:registerDependentBean
这边又引入了一个跟 dependentBeanMap 类似的缓存,dependenciesForBeanMap:beanName -> beanName 对应的 bean 依赖的所有 bean 的 beanName 集合。
这两个缓存很容易搞混,举个简单例子:例如 B 依赖了 A,则 dependentBeanMap 缓存中应该存放一对映射:其中 key 为 A,value 为含有 B 的 Set;而 dependenciesForBeanMap 缓存中也应该存放一对映射:其中 key 为:B,value 为含有 A 的 Set。
代码块8:getSingleton
5.创建单例前的操作,7.创建单例后的操作,这两个方法是对应的,见代码块9详解。
6.执行 singletonFactory 的 getObject 方法获取 bean 实例,该方法会走文章开头 doGetBean 方法的注释 9.1.1。
8.如果是新的单例对象,将 beanName 和对应的单例对象添加到缓存中,见代码块详解。
代码块9:beforeSingletonCreation、afterSingletonCreation
inCreationCheckExclusions 是要在创建检查排除掉的 beanName 集合,正常为空,可以不管。这边主要是引入了 singletonsCurrentlyInCreation 缓存:当前正在创建的 bean 的 beanName 集合。在 beforeSingletonCreation 方法中,通过添加 beanName 到该缓存,可以预防出现构造器循环依赖的情况。
为什么无法解决构造器循环依赖?
我们之前在 Spring IoC:finishBeanFactoryInitialization 详解 中的代码块7提过,getSingleton 方法是解决循环引用的核心代码。解决逻辑的第一句话:“我们先用构造函数创建一个 “不完整” 的 bean 实例”,从这句话可以看出,构造器循环依赖是无法解决的,因为当构造器出现循环依赖,我们连 “不完整” 的 bean 实例都构建不出来。Spring 能解决的循环依赖有:通过 setter 注入的循环依赖、通过属性注入的循环依赖。
代码块:addSingleton
代码块:beforePrototypeCreation、afterPrototypeCreation
该方法和代码块9的两个方法类似。主要是在进行 bean 实例的创建前,将 beanName 添加到 prototypesCurrentlyInCreation 缓存;bean 实例创建后,将 beanName 从 prototypesCurrentlyInCreation 缓存中移除。这边 prototypesCurrentlyInCreation 存放的类型为 Object,在只有一个 beanName 的时候,直接存该 beanName,也就是 String 类型;当有多个 beanName 时,转成 Set 来存放。
总结
本文介绍了获取 bean 实例的大部分内容,包括先从缓存中检查、 FactoryBean 的 bean 创建、实例化自己的依赖(depend-on 属性)、创建 bean 实例的前后一些标记等,在下篇文章中,将解析创建 bean 的内容。
推荐阅读
springçç»ä»¶åä½ç¨(springclouç»ä»¶)
ç®è¦è¯´æspringçä¸¤ä¸ªæ ¸å¿åè½åå ¶ä½ç¨
springæ¡æ¶æ¯ä¸ä¸ªè½»é级çå¼æºä»ä¼æ¡æ¶ï¼æ¯ä¸ä¸ªIOCåAOP容å¨ãå®æ¯ä½ä¾µå ¥å¼è®¾è®¡ï¼ç¬ç«äºåç§åºç¨æå¡å¨ï¼
ä¾èµæ³¨å ¥çç¹ç¹å°ç»ä»¶å ³ç³»éæåï¼éä½è¦å度
æ§å¶å转ï¼IOCï¼ï¼ç¨æ¥éä½ç¨åºä»£ç ä¹é´çè¦å度ï¼ä½¿æ´ä¸ªç¨åºä½ç³»ç»ææ´å çµæ´»ï¼åæ¶å°ç±»çå建åä¾èµå ³ç³»åå¨é ç½®æ件éï¼ç±é ç½®æä»¶æ³¨å ¥ï¼è¾¾å°æ¾è¦åçææã
DIï¼ä¾èµæ³¨å ¥ï¼
设å¼æ³¨å ¥ï¼åºå±å®ç°setæ¹æ³èµå¼ã
使ç¨æé å¨æ³¨å ¥ï¼ç½©å³åºå±å®ç°æé æ¹æ³æ³¨å ¥ï¼æ ¹æ®beanä¸çåæ°ç±»åååæ°æ°éï¼å¯»æ¾å¯¹åºçæé æ¹æ³ã
èªå¨è£ é ï¼ä¸è½èªå¨è£ é æè°çç®åç±»åå æ¬åºæ¬ç±»åï¼å符串åéåç±»é常ç¨æ¥èªå¨è£ é 对象
æç §å称æ¥èªå¨è£ é åºå±å®ç°æ¯setæ¹æ³
æç §ç±»åæ¥èªå¨è£ é åºå±å®ç°æ¯setæ¹æ³
2.é¢ååé¢ç¼ç¨ï¼AOPï¼
æ主è¦çä½ç¨ï¼å¯ä»¥å¨ä¸ä¿®æ¹æºä»£ç çæ åµä¸ï¼ç»ç®æ æ¹æ³å¨ææ·»å åè½
ä¸å¡é»è¾å°±ä¸å¿çå¤çå®é éæ±ï¼éç¨çå¢å¼ºåè½ç¬ç«åºæ¥ãå°å®å ¨äºå¡çç¨åºé»è¾ç¸å¯¹ç¬ç«çåè½æ½ååºæ¥ï¼å©ç¨Springçé ç½®æ件å°è¿äºåè½æè¿å»ï¼å®ç°äºæç §åé¢ç¼ç¨ï¼æé«äºå¤ç¨æ§ã
åç§å¢å¼ºæ¹å¼ï¼
åç½®å¢å¼ºï¼å¨æ ¸å¿åè½ä¹åæ§è¡çé¢å¤åè½
åç½®å¢å¼ºï¼å¨æ ¸ç©ææ å¿åè½ä¹åæ§è¡çé¢å¤åè½
å¼å¸¸å¢å¼ºï¼å¨æ ¸å¿åè½åçå¼å¸¸æ¶æ§è¡çé¢å¤åè½
ç¯ç»å¢å¼ºï¼å¨æ ¸å¿åè½ä¹å以åä¹åæ§è¡çé¢å¤åè½
springå å«åªäºç»ä»¶
Springæ¡æ¶æ¯ä¸ä¸ªåå±æ¶æï¼ç±7个å®ä¹è¯å¥½ç模åç»æè¢å¤ãSpring模åæ建å¨æ ¸å¿å®¹å¨ä¹ä¸ï¼æ ¸å¿å®¹å¨ç«å®´å®ä¹äºå建ãé ç½®å管çbeançæ¹å¼ï¼ç»æSpringæ¡æ¶çæ¯ä¸ªæ¨¡åï¼æç»ä»¶ï¼é½å¯ä»¥åç¬åå纤æ¹å¨ï¼æè ä¸å ¶ä»ä¸ä¸ªæå¤ä¸ªæ¨¡åèåå®ç°ã
SpringMVC主è¦ç»ä»¶è¯´æ1ãå端æ§å¶å¨DispatcherServletï¼ä¸éè¦å¼åï¼ç±æ¡æ¶æä¾ãæ ¸å¿ãï¼
DispatcherServletæ¯SpringMVCçå ¥å£å½æ°ãæ¥æ¶è¯·æ±ï¼ååºç»æï¼ç¸å½äºè½¬åå¨ç¢§ç®ï¼ä¸å¤®å¤çå¨ãæäºDispatcherServletï¼å¯ä»¥å¤§å¤§åå°å ¶å®ç»ä»¶ä¹é´çè¦å度ã
ç¨æ·è¯·æ±å°è¾¾å端æ§å¶å¨ï¼å°±ç¸å½äºmvc模å¼ä¸çcï¼DispatcherServletæ¯æ´ä¸ªæµç¨æ§å¶çä¸å¿ï¼ç±å®è°ç¨å ¶å®ç»ä»¶æ¥å¤çç¨æ·ç请æ±ã
2ãå¤çå¨æ å°å¨HandlerMapping(ä¸éè¦å¼åï¼ç±æ¡æ¶æä¾)
HandlerMappingè´è´£æ ¹æ®ç¨æ·è¯·æ±ï¼URLï¼ï¼æ¾å°ç¸åºçHandlerå³å¤çå¨ï¼Controllerï¼ï¼SpringMVCæä¾äºä¸åæ å°å¨å®ç°çä¸åæ å°æ¹å¼ï¼ä¾å¦ï¼é ç½®æ件æ¹å¼ï¼å®ç°æ¥å£æ¹å¼ï¼æ³¨è§£æ¹å¼çã
3ãå¤çå¨éé å¨HandlerAdapter(ä¸éè¦å¼åï¼ç±æ¡æ¶æä¾)
æç §ç¹å®è§åï¼HandlerAdapterè¦æ±çè§åï¼å»æ§è¡Handlerï¼éè¿HandlerAdapter对å¤çå¨è¿è¡æ§è¡ï¼è¿æ¯éé å¨æ¨¡å¼çåºç¨ï¼éè¿æ©å±éé å¨å¯ä»¥å¯¹æ´å¤ç±»åçå¤çå¨è¿è¡å¤çã
4ãå¤çå¨Handler(éè¦å·¥ç¨å¸å¼å)
Handleræ¯ç»§DispatcherServletå端æ§å¶å¨çå端æ§å¶å¨ï¼å¨DispatcherServletçæ§å¶ä¸ï¼Handlerå¯¹å ·ä½çç¨æ·è¯·æ±è¿è¡å¤çãç±äºHandleræ¶åå°å ·ä½çç¨æ·ä¸å¡è¯·æ±ï¼æ以ä¸è¬æ åµä¸éè¦å·¥ç¨å¸æ ¹æ®ä¸å¡éæ±æ¥å¼åHandlerã
5ãè§å¾è§£æå¨ViewResolver(ä¸éè¦å¼åï¼ç±æ¡æ¶æä¾)
ä½ç¨ï¼è¿è¡è§å¾è§£æï¼æ ¹æ®é»è¾è§å¾å解ææçæ£çè§å¾ï¼Viewï¼ï¼ViewResolverè´è´£å°å¤çç»æçæViewè§å¾ãé¦å ï¼æ ¹æ®é»è¾è§å¾å解ææç©çè§å¾åï¼å³å ·ä½ç页é¢å°åï¼ï¼åçæViewè§å¾å¯¹è±¡ï¼æå对Viewè¿è¡æ¸²æï¼å°å¤çç»æéè¿é¡µé¢å±ç¤ºç»ç¨æ·ã
SpringMVCæ¡æ¶æä¾äºå¾å¤çViewè§å¾ç±»åï¼å æ¬ï¼jstlViewãfreemarkerViewãpdfViewçãä¸è¬æ åµä¸ï¼éè¦éè¿é¡µé¢æ ç¾æ页æ¸é®é¢æ¨¡çææ¯ï¼å°æ¨¡åæ°æ®éè¿é¡µé¢å±ç¤ºç»ç¨æ·ï¼è¿éè¦ç±å·¥ç¨å¸æ ¹æ®ä¸æ §å·§ä¸å¡éæ±å¼åå ·ä½ç页é¢ã
6ãè§å¾View(éè¦å·¥ç¨å¸å¼å)
Viewæ¯ä¸ä¸ªæ¥å£ï¼å®ç°ç±»æå¯ä»¥æ¯æä¸åçViewç±»åï¼jspãfreemarkerãpdf...ï¼
æ»ç»ï¼å¤çå¨Handlerï¼ä¹å°±æ¯å¹³å¸¸è¯´çControlleræ§å¶å¨ï¼ä»¥åè§å¾å±Viewï¼é½æ¯éè¦èªè¡å¼åçãå ¶ä»çä¸äºç»ä»¶ï¼å¦ï¼å端æ§å¶å¨DispatcherServletãå¤çå¨æ å°å¨HandlerMappingãå¤çå¨éé å¨HandlerAdapterçé½æ¯ç±æ¡æ¶æä¾ã
spring主è¦çä½ç¨ï¼Springæ¡æ¶æ¯ä¸ºäºè§£å³ä¼ä¸åºç¨å¼åçå¤ææ§èå建çã
Springçç¨éä¸ä» ä» éäºæå¡å¨ç«¯çå¼åãä»ç®åæ§ãå¯æµè¯æ§åæ¾è¦åæ§è§åº¦èè¨ï¼ç»å¤§é¨åJavaåºç¨é½å¯ä»¥ä»Springä¸åçã使ç¨åºæ¬çJavaBean代æ¿EJBï¼å¹¶æä¾äºæ´å¤çä¼ä¸åºç¨åè½ã
æ©å±èµæ
ä¼ç¹
1ãJAVAEEåºè¯¥æ´å 容æ使ç¨ã
2ãé¢å对象ç设计æ¯ä»»ä½å®ç°ææ¯ï¼æ¯å¦JAVAEEï¼é½éè¦ã
3ãé¢åæ¥å£ç¼ç¨ï¼èä¸æ¯é对类ç¼ç¨ãSpringå°ä½¿ç¨æ¥å£çå¤æ度éä½å°é¶ãï¼é¢åæ¥å£ç¼ç¨æåªäºå¤æ度ï¼
4ã代ç åºè¯¥æäºæµè¯ãSpringæ¡æ¶ä¼å¸®å©ä½ ï¼ä½¿ä»£ç çæµè¯å¤è¡¡æ´å ç®åã
5ãJavaBeanæä¾äºåºç¨ç¨åºé ç½®çæ好æ¹æ³ã
6ãå¨Javaä¸ï¼å·²æ£æ¥å¼å¸¸ï¼Checkedexceptionï¼è¢«è¿åº¦ä½¿ç¨ãæ¡æ¶ä¸åºè¯¥è¿«ä½¿ä½ ææ碧è·ä¸æè´ºåè½æ¢å¤çå¼å¸¸ã
åèèµææ¥æºï¼ç¾åº¦ç¾ç§-springæ¡æ¶
如何快速读懂项目源码javaWeb
一:学会如何读一个JavaWeb项目源代码 步骤:表结构->web.xml->mvc->db->spring
ioc->log-> 代码
1、先了解项目数据库的表结构,这个方面是最容易忘记 的,有时候我们只顾着看每一个方法是怎么进行的,却没
有去了解数据库之间的主外键关联。其实如果先了解数据 库表结构,再去看一个方法的实现会更加容易。
2、然后需要过一遍web.xml,知道项目中用到了什么拦
截器,监听器,过滤器,拥有哪些配置文件。如果是拦截 器,一般负责过滤请求,进行AOP 等;如果是监 可能是定时任务,初始化任务;配置文件有如使用了 spring
后的读取mvc 相关,db 相关,service 相关,aop 相关的文件。
3、查看拦截器,监听器代码,知道拦截了什么请求,这
个类完成了怎样的工作。有的人就是因为缺少了这一步, 自己写了一个action,配置文件也没有写错,但是却怎么
调试也无法进入这个action,直到别人告诉他,请求被拦
4、接下来,看配置文件,首先一定是mvc相关的,如 springmvc
中,要请求哪些请求是静态资源,使用了哪些 view 策略,controller 注解放在哪个包下等。 然后是db 相关配置文件,看使用了什么数据库,使用了
什么orm框架,是否开启了二级缓存,使用哪种产品作 为二级缓存,事务管理的处理,需要扫描的实体类放在什 么位置。最后是spring 核心的ioc
功能相关的配置文件, 知道接口与具体类的注入大致是怎样的。当然还有一些如 apectj 置文件,也是在这个步骤中完成
5、log
相关文件,日志的各个级别是如何处理的,在哪些 地方使用了log 记录日志
6、从上面几点后知道了整个开源项目的整体框架,阅读 每个方法就不再那么难了。
7、当然如果有项目配套的开发文档也是要阅读的。
IOCåAOPçåºå«ï¼
ä»ä¹æ¯IoC
IocâInversion of Controlï¼å³âæ§å¶å转âï¼ä¸æ¯ä»ä¹ææ¯ï¼èæ¯ä¸ç§è®¾è®¡ææ³ãå¨Javaå¼åä¸ï¼Iocæå³çå°ä½ 设计好ç对象交ç»å®¹å¨æ§å¶ï¼èä¸æ¯ä¼ ç»çå¨ä½ ç对象å é¨ç´æ¥æ§å¶ãå¦ä½ç解好Iocå¢ï¼ç解好Iocçå ³é®æ¯è¦æç¡®âè°æ§å¶è°ï¼æ§å¶ä»ä¹ï¼ä¸ºä½æ¯å转ï¼æå转就åºè¯¥ææ£è½¬äºï¼ï¼åªäºæ¹é¢å转äºâï¼é£æ们æ¥æ·±å ¥åæä¸ä¸ï¼
æ§å¶æ¯ä»ä¹ï¼ä¼ ç»Java SEç¨åºè®¾è®¡ï¼æ们ç´æ¥å¨å¯¹è±¡å é¨éè¿newè¿è¡å建对象ï¼æ¯ç¨åºä¸»å¨å»å建ä¾èµå¯¹è±¡ï¼èIoCæ¯æä¸é¨ä¸ä¸ªå®¹å¨æ¥å建è¿äºå¯¹è±¡ï¼å³ç±Ioc容å¨æ¥æ§å¶å¯¹è±¡çå建ï¼è°æ§å¶è°ï¼å½ç¶æ¯IoC 容å¨æ§å¶äºå¯¹è±¡ï¼æ§å¶ä»ä¹ï¼é£å°±æ¯ä¸»è¦æ§å¶äºå¤é¨èµæºè·åï¼ä¸åªæ¯å¯¹è±¡å æ¬æ¯å¦æ件çï¼ã
为ä½æ¯å转ï¼åªäºæ¹é¢å转äºï¼æå转就ææ£è½¬ï¼ä¼ ç»åºç¨ç¨åºæ¯ç±æ们èªå·±å¨å¯¹è±¡ä¸ä¸»å¨æ§å¶å»ç´æ¥è·åä¾èµå¯¹è±¡ï¼ä¹å°±æ¯æ£è½¬ï¼èå转åæ¯ç±å®¹å¨æ¥å¸®å¿å建åæ³¨å ¥ä¾èµå¯¹è±¡ï¼ä¸ºä½æ¯å转ï¼å 为ç±å®¹å¨å¸®æ们æ¥æ¾åæ³¨å ¥ä¾èµå¯¹è±¡ï¼å¯¹è±¡åªæ¯è¢«å¨çæ¥åä¾èµå¯¹è±¡ï¼æ以æ¯å转ï¼åªäºæ¹é¢å转äºï¼ä¾èµå¯¹è±¡çè·å被å转äºã
IoCè½åä»ä¹
IoCä¸æ¯ä¸ç§ææ¯ï¼åªæ¯ä¸ç§ææ³ï¼ä¸ä¸ªéè¦çé¢å对象ç¼ç¨çæ³åï¼å®è½æ导æ们å¦ä½è®¾è®¡åºæ¾è¦åãæ´ä¼è¯çç¨åºãä¼ ç»åºç¨ç¨åºé½æ¯ç±æ们å¨ç±»å é¨ä¸»å¨å建ä¾èµå¯¹è±¡ï¼ä»è导è´ç±»ä¸ç±»ä¹é´é«è¦åï¼é¾äºæµè¯ï¼æäºIoC容å¨åï¼æå建åæ¥æ¾ä¾èµå¯¹è±¡çæ§å¶æ交ç»äºå®¹å¨ï¼ç±å®¹å¨è¿è¡æ³¨å ¥ç»å对象ï¼æ以对象ä¸å¯¹è±¡ä¹é´æ¯æ¾æ£è¦åï¼è¿æ ·ä¹æ¹ä¾¿æµè¯ï¼å©äºåè½å¤ç¨ï¼æ´éè¦çæ¯ä½¿å¾ç¨åºçæ´ä¸ªä½ç³»ç»æåå¾é常çµæ´»ã
å ¶å®IoC对ç¼ç¨å¸¦æ¥çæ大æ¹åä¸æ¯ä»ä»£ç ä¸ï¼èæ¯ä»ææ³ä¸ï¼åçäºâ主ä»æ¢ä½âçååãåºç¨ç¨åºåæ¬æ¯è大ï¼è¦è·åä»ä¹èµæºé½æ¯ä¸»å¨åºå»ï¼ä½æ¯å¨IoC/DIææ³ä¸ï¼åºç¨ç¨åºå°±åæ被å¨çäºï¼è¢«å¨ççå¾ IoC容å¨æ¥åå»ºå¹¶æ³¨å ¥å®æéè¦çèµæºäºã
IoCåDI
DIâDependency Injectionï¼å³âä¾èµæ³¨å ¥âï¼æ¯ç»ä»¶ä¹é´ä¾èµå ³ç³»ç±å®¹å¨å¨è¿è¡æå³å®ï¼å½¢è±¡ç说ï¼å³ç±å®¹å¨å¨æçå°æ个ä¾èµå ³ç³»æ³¨å ¥å°ç»ä»¶ä¹ä¸ãä¾èµæ³¨å ¥çç®ç并é为软件系ç»å¸¦æ¥æ´å¤åè½ï¼èæ¯ä¸ºäºæåç»ä»¶éç¨çé¢çï¼å¹¶ä¸ºç³»ç»æ建ä¸ä¸ªçµæ´»ãå¯æ©å±çå¹³å°ãéè¿ä¾èµæ³¨å ¥æºå¶ï¼æ们åªéè¦éè¿ç®åçé ç½®ï¼èæ éä»»ä½ä»£ç å°±å¯æå®ç®æ éè¦çèµæºï¼å®æèªèº«çä¸å¡é»è¾ï¼èä¸éè¦å ³å¿å ·ä½çèµæºæ¥èªä½å¤ï¼ç±è°å®ç°ã
注ï¼å¦ææ³è¦æ´å æ·±å ¥çäºè§£IoCåDIï¼è¯·åè大å¸çº§äººç©Martin Fowlerçä¸ç¯ç»å ¸æç« ãInversion of Control Containers and the Dependency Injection patternãï¼åæå°åï¼/articles/injection.htmlã
AOPï¼é¢ååé¢ç¼ç¨
ä»ä¹æ¯AOPï¼
æ¦å¿µï¼å¨è½¯ä»¶ä¸ï¼AOP为Aspect Oriented Programmingç缩åï¼æ为ï¼é¢ååé¢ç¼ç¨ï¼éè¿é¢ç¼è¯æ¹å¼åè¿è¡æå¨æ代çå®ç°ç¨åºåè½çç»ä¸ç»´æ¤çä¸ç§ææ¯ãAOPæ¯OOPç延ç»ï¼æ¯è½¯ä»¶å¼åä¸çä¸ä¸ªçç¹ï¼ä¹æ¯Springæ¡æ¶ä¸çä¸ä¸ªéè¦å 容ï¼æ¯å½æ°å¼ç¼ç¨çä¸ç§è¡çèåãå©ç¨AOPå¯ä»¥å¯¹ä¸å¡é»è¾çå个é¨åè¿è¡é离ï¼ä»è使å¾ä¸å¡é»è¾åé¨åä¹é´çè¦å度éä½ï¼æé«ç¨åºçå¯éç¨æ§ï¼åæ¶æé«äºå¼åçæçãï¼ç¾åº¦ç¾ç§ï¼
ç®åç说ï¼å°±æ¯å°ç¨åºä¸éå¤ç代ç æ½ååºæ¥ï¼å¨éè¦æ§è¡çæ¶åï¼ä½¿ç¨å¨æ代ççææ¯ï¼å¨ä¸ä¿®æ¹æºç çåºç¡ä¸ï¼å¯¹æ们çå·²ææ¹æ³è¿è¡å¢å¼ºã
AOPçä½ç¨åä¼å¿ï¼
ä½ç¨ï¼ä»å®ä¹ä¸æ¥çï¼å°±æ¯ä¸ºäºå¨ç¨åºè¿è¡æé´ï¼ä¸ä¿®æ¹æºç 对已ææ¹æ³è¿è¡å¢å¼ºã
ä¼å¿ï¼åå°éå¤ä»£ç æ交äºå¼åæç ç»´æ¤æ¹ä¾¿
å®ç°æ¹å¼ï¼ å°±æ¯å¨æ代ççææ¯
å ·ä½çä½ç¨ï¼å®ç°äºå¡çæ§å¶ æ¥å¿ å å®å ¨æ¨¡å
æ³ç³»ç»çå¦ä¹ ç¼ç¨å¯ä»¥æ¥æè¿ççï¼å¸æ对æ¨ææ帮å©ï¼~