ï»??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲精品视频免费观看,91免费精品国自产拍在线不卡,国产精品欧美极品http://www.aygfsteel.com/caizh2009/category/47775.html与大家共同成é•?/description>zh-cnTue, 15 Feb 2011 08:15:44 GMTTue, 15 Feb 2011 08:15:44 GMT60Spring 框架的设计理念与设计模式分析http://www.aygfsteel.com/caizh2009/archive/2011/02/15/344368.htmlž®èœæ¯›æ¯›ž®èœæ¯›æ¯›Tue, 15 Feb 2011 08:13:00 GMThttp://www.aygfsteel.com/caizh2009/archive/2011/02/15/344368.htmlhttp://www.aygfsteel.com/caizh2009/comments/344368.htmlhttp://www.aygfsteel.com/caizh2009/archive/2011/02/15/344368.html#Feedback0http://www.aygfsteel.com/caizh2009/comments/commentRss/344368.htmlhttp://www.aygfsteel.com/caizh2009/services/trackbacks/344368.html

½Ž€ä»‹ï¼š Spring ä½œäØ“çŽ°åœ¨æœ€ä¼˜ç§€çš„æ¡†æž¶ä¹‹ä¸€åQŒå·²è¢«å¹¿æ³›çš„使用åQŒåƈ且有很多对其分析的文章。本文将从另外一个视角试囑։–析出 Spring 框架的作者设è®?Spring 框架的骨骼架构的设计理念åQŒæœ‰é‚£å‡ ä¸ªæ ¸å¿ƒç»„ä»Óž¼Ÿä¸ÞZ»€ä¹ˆéœ€è¦è¿™äº›ç»„ä»Óž¼Ÿå®ƒä»¬åˆæ˜¯å¦‚何¾l“合在一èµähž„æˆ?Spring 的骨骼架构? Spring çš? AOP ç‰ÒŽ€§åˆæ˜¯å¦‚何利用这些基¼‹€çš„骨骼架构来工作的? Spring 中又使用了那些设计模式来完成它的˜q™ç§è®¾è®¡çš„?它的˜q™ç§è®¾è®¡ç†å¿µå¯¹å¯¹æˆ‘们以后的èÊY件设计有何启½Cºï¼Ÿæœ¬æ–‡ž®†è¯¦¾l†è§£½{”这些问题ã€?/p>

Spring 的骨骼架�/strong>

Spring æ€Õd…±æœ‰åå‡ ä¸ª¾l„äšgåQŒä½†æ˜¯çœŸæ­£æ ¸å¿ƒçš„¾l„äšg只有几个åQŒä¸‹é¢æ˜¯ Spring 框架的æ€ÖM½“架构图:


å›?1 .Spring 框架的æ€ÖM½“æž¶æž„å›?/font>
å›?1 .Spring 框架的æ€ÖM½“æž¶æž„å›? src=

从上图中可以看出 Spring 框架中的核心¾l„äšg只有三个åQšCore、Context å’?Beansã€‚å®ƒä»¬æž„å»ø™“v了整ä¸?Spring 的骨骼架构。没有它们就不可能有 AOP、Web ½{‰ä¸Šå±‚çš„ç‰ÒŽ€§åŠŸèƒ½ã€‚ä¸‹é¢ä¹Ÿž®†ä¸»è¦ä»Ž˜q™ä¸‰ä¸ªç»„件入手分æž?Springã€?/p>

Spring 的设计理�/strong>

前面介绍äº?Spring 的三个核心组ä»Óž¼Œå¦‚果再在它们三个中选出核心的话åQŒé‚£ž®±éž Beans ¾l„äšg莫属了,ä¸ÞZ½•˜q™æ ·è¯ß_¼Œå…¶å®ž Spring ž®±æ˜¯é¢å‘ Bean 的编½E‹ï¼ˆBOP,Bean Oriented ProgrammingåQ‰ï¼ŒBean åœ?Spring 中才是真正的主角ã€?/p>

Bean åœ?Spring 中作用就åƒ?Object å¯?OOP çš„æ„ä¹‰ä¸€æ øP¼Œæ²¡æœ‰å¯¹è±¡çš„æ¦‚念就像没有面向对象编½E‹ï¼ŒSpring 中没æœ? Bean 也就没有 Spring 存在的意义。就像一‹Æ¡æ¼”凸™ˆžå°éƒ½å‡†å¤‡å¥½äº†ä½†æ˜¯å´æ²¡æœ‰æ¼”员一栗÷€‚äØ“ä»€ä¹ˆè¦ Bean ˜q™ç§è§’色 Bean æˆ–è€…äØ“ä½•åœ¨ Spring 如此重要åQŒè¿™ç”?Spring 框架的设计目标决定,Spring ä¸ÞZ½•如此‹¹è¡ŒåQŒæˆ‘们用 Spring 的原因是什么,æƒÏxƒ³ä½ ä¼šå‘现原来 Spring 解决了一个非常关键的问题他可以让你把对象之间的依赖关¾p»è{而用配置文äšg来管理,也就是他的依赖注入机制。而这个注入关¾pÕdœ¨ä¸€ä¸ªå« Ioc 容器中管理,é‚?Ioc 容器中有又是什么就是被 Bean 包裹的对象。Spring 正是通过把对象包装在 Bean 中而达到对˜q™äº›å¯¹è±¡½Ž¡ç†ä»¥åŠä¸€äº›åˆ—额外操作的目的ã€?/p>

它这¿Uè®¾è®¡ç­–略完全类ä¼égºŽ Java 实现 OOP 的设计理念,当然äº?Java 本èín的设计要æ¯?Spring 复杂太多太多åQŒä½†æ˜¯éƒ½æ˜¯æž„å»ÞZ¸€ä¸ªæ•°æ®ç»“构,然后æ ÒŽ®˜q™ä¸ªæ•°æ®¾l“构设计他的生存环境åQŒåƈ让它在这个环境中按照一定的规律在不停的˜qåЍåQŒåœ¨å®ƒä»¬çš„不停运动中è®? 计一¾pÕdˆ—与环境或者与其他个体完成信息交换。这æ ähƒ³æ¥å›ž˜q‡å¤´æƒÏxƒ³æˆ‘们用到的其他框枉™ƒ½æ˜¯å¤§æ…¨ç±»ä¼¼çš„设计理念ã€?/p>

核心¾l„äšg如何协同工作

前面è¯?Bean æ˜?Spring 中关键因素,é‚?Context å’?Core 又有何作用呢åQŸå‰é¢å§ Bean 比作一场演å‡ÞZ¸­çš„æ¼”员的话,é‚?Context ž®±æ˜¯˜q™åœºæ¼”出的舞台背景,è€?Core 应该ž®±æ˜¯æ¼”出的道具了。只有他们在一èµäh‰èƒ½å…·å¤‡èƒ½æ¼”å‡ºä¸€åœºå¥½æˆçš„æœ€åŸºæœ¬çš„æ¡ä»¶ã€‚å½“ç„¶æœ‰æœ€åŸºæœ¬çš„æ¡ä»¶è¿˜ä¸èƒ½ä½¿è¿™åœºæ¼”å‡ø™„±é¢–而出åQŒè¿˜è¦ä»–表演的节目èƒö够的¾_? 彩,˜q™äº›èŠ‚ç›®ž®±æ˜¯ Spring 能提供的特色功能了ã€?/p>

我们知道 Bean 包装的是 ObjectåQŒè€?Object 必然有数据,如何¾l™è¿™äº›æ•°æ®æä¾›ç”Ÿå­˜çŽ¯å¢ƒå°±æ˜?Context 要解决的问题åQŒå¯¹ Context 来说他就是要发现每个 Bean 之间的关¾p»ï¼Œä¸ºå®ƒä»¬å¾ç«‹è¿™¿Uå…³¾pÕdƈ且要¾l´æŠ¤å¥½è¿™¿Uå…³¾p…R€‚所ä»?Context ž®±æ˜¯ä¸€ä¸?Bean 关系的集合,˜q™ä¸ªå…³ç³»é›†åˆåˆå« Ioc 容器åQŒä¸€æ—¦å¾ç«‹è“v˜q™ä¸ª Ioc 容器å?Spring ž®±å¯ä»¥äؓ你工作了。那 Core ¾l„äšg又有什么用武之地呢åQŸå…¶å®?Core ž®±æ˜¯å‘现、徏立和¾l´æŠ¤æ¯ä¸ª Bean 之间的关¾pÀL‰€éœ€è¦çš„ä¸€äº›åˆ—çš„å·¥å…øP¼Œä»Žè¿™ä¸ªè§’度看来,Core ˜q™ä¸ª¾l„äšgå? Util 更能让你理解ã€?/p>

它们之间可以用下图来表示åQ?/p>
å›?2. 三个¾l„äšg关系
å›?2. 三个¾l„äšg关系

核心¾l„äšg详解

˜q™é‡Œž®†è¯¦¾l†ä»‹¾læ¯ä¸ªç»„件内部类的层‹Æ¡å…³¾p»ï¼Œä»¥åŠå®ƒä»¬åœ¨è¿è¡Œæ—¶çš„æ—¶åºé¡ºåºã€‚我们在使用 Spring 是应该注意的地方ã€?/p>

Bean ¾l„äšg

前面已经说明äº?Bean ¾l„äšgå¯?Spring 的重要性,下面看看 Bean ˜q™ä¸ª¾l„äšg式怎么设计的。Bean ¾l„äšgåœ?Spring çš? org.springframework.beans 包下。这个包下的所有类主要解决了三件事åQšBean 的定义、Bean 的创å»ÞZ»¥åŠå¯¹ Bean 的解析。对 Spring çš„ä‹É用者来说唯一需要关心的ž®±æ˜¯ Bean 的创建,其他两个ç”?Spring 在内部帮你完成了åQŒå¯¹ä½ æ¥è¯´æ˜¯é€æ˜Žçš„ã€?/p>

Spring Bean 的创建时典型的工厂模式,他的™å¶çñ”接口æ˜?BeanFactoryåQŒä¸‹å›¾æ˜¯˜q™ä¸ªå·¥åŽ‚çš„ç‘ô承层‹Æ¡å…³¾p»ï¼š


å›?4. Bean 工厂的ç‘ô承关¾p?/font>
å›?4. Bean 工厂的ç‘ô承关¾p? src=

BeanFactory 有三个子¾c»ï¼šListableBeanFactory、HierarchicalBeanFactory å’? AutowireCapableBeanFactory。但是从上图中我们可以发现最¾lˆçš„默认实现¾cÀL˜¯ DefaultListableBeanFactoryåQŒä»–实现了所有的接口。那ä¸ÞZ½•要定义这么多层次的接口呢åQŸæŸ¥é˜…这些接口的源码和说明发玎ͼŒæ¯ä¸ªæŽ¥å£ 都有他ä‹É用的场合åQŒå®ƒä¸»è¦æ˜¯äؓ了区分在 Spring 内部在操作过½E‹ä¸­å¯¹è±¡çš„传递和转化˜q‡ç¨‹ä¸­ï¼Œå¯¹å¯¹è±¡çš„æ•°æ®è®‰K—®æ‰€åšçš„限制。例å¦? ListableBeanFactory 接口表示˜q™äº› Bean 是可列表的,è€?HierarchicalBeanFactory 表示的是˜q™äº› Bean 是有¾l§æ‰¿å…³ç³»çš„,也就是每ä¸?Bean 有可能有çˆ?Bean。AutowireCapableBeanFactory 接口定义 Bean 的自动装配规则。这四个接口共同定义äº?Bean 的集合、Bean 之间的关¾p…R€ä»¥å?Bean è¡ŒäØ“ã€?/p>

Bean 的定义主要有 BeanDefinition 描述åQŒå¦‚下图说明了这些类的层‹Æ¡å…³¾p»ï¼š


�5. Bean 定义的类层次关系�/font>
�5. Bean 定义的类层次关系� src=

Bean 的定义就是完整的描述了在 Spring 的配¾|®æ–‡ä»¶ä¸­ä½ å®šä¹‰çš„ <bean/> 节点中所有的信息åQŒåŒ…括各¿Uå­èŠ‚ç‚¹ã€‚å½“ Spring 成功解析你定义的一ä¸?<bean/> 节点后,åœ?Spring 的内部他ž®Þp¢«è½¬åŒ–æˆ?BeanDefinition 对象。以后所有的操作都是对这个对象完成的ã€?/p>

Bean 的解析过½E‹éžå¸¸å¤æ‚,功能被分的很¾l†ï¼Œå› äØ“˜q™é‡Œéœ€è¦è¢«æ‰©å±•的地方很多,必须保证有èƒö够的灉|´»æ€§ï¼Œä»¥åº”对可能的变化。Bean 的解析主要就是对 Spring 配置文äšg的解析。这个解析过½E‹ä¸»è¦é€šè¿‡ä¸‹å›¾ä¸­çš„¾cÕd®Œæˆï¼š


�6. Bean 的解析类
�6. Bean 的解析类

当然˜q˜æœ‰å…·ä½“å¯?tag çš„è§£æžè¿™é‡ŒåÆˆæ²¡æœ‰åˆ—å‡ºã€?/p>

Context ¾l„äšg

Context åœ?Spring çš?org.springframework.context 包下åQŒå‰é¢å·²¾lè®²è§£äº† Context ¾l„äšgåœ? Spring 中的作用åQŒä»–实际上就是给 Spring 提供一个运行时的环境,用以保存各个对象的状态。下面看一下这个环境是如何构徏的ã€?/p>

ApplicationContext æ˜?Context 的顶¾U§çˆ¶¾c»ï¼Œä»–除了能标识一个应用环境的基本信息外,他还¾l§æ‰¿äº†äº”个接口,˜q™äº”个接口主要是扩展äº?Context 的功能。下面是 Context 的类¾l“构图:


å›?7. Context 相关的类¾l“æž„å›?/font>
å›?7. Context 相关的类¾l“æž„å›? src=

åQˆæŸ¥çœ?å›?7 的清晰版æœ?/font>。)

从上图中可以看出 ApplicationContext ¾l§æ‰¿äº?BeanFactoryåQŒè¿™ä¹Ÿè¯´æ˜Žäº† Spring 容器中运行的ä¸ÖM½“对象æ˜? BeanåQŒå¦å¤?ApplicationContext ¾l§æ‰¿äº?ResourceLoader 接口åQŒä‹Éå¾?ApplicationContext 可以讉K—®åˆîC“Q何外部资源,˜q™å°†åœ?Core 中详¾l†è¯´æ˜Žã€?/p>

ApplicationContext 的子¾cÖM¸»è¦åŒ…含两个方面:

  1. ConfigurableApplicationContext 表示è¯?Context 是可修改的,也就是在构徏 Context 中用户可以动态添加或修改已有的配¾|®ä¿¡æ¯ï¼Œå®ƒä¸‹é¢åˆæœ‰å¤šä¸ªå­¾c»ï¼Œå…¶ä¸­æœ€¾lå¸¸ä½¿ç”¨çš„æ˜¯å¯æ›´æ–°çš„ ContextåQŒå³ AbstractRefreshableApplicationContext ¾c…R€?
  2. WebApplicationContext ™å‘֐æ€ä¹‰åQŒå°±æ˜¯äØ“ web 准备çš?Context 他可以直接访问到 ServletContextåQŒé€šå¸¸æƒ…况下,˜q™ä¸ªæŽ¥å£ä½¿ç”¨çš„å°‘ã€?

再往下分ž®±æ˜¯æŒ‰ç…§æž„徏 Context 的文件类型,接着ž®±æ˜¯è®‰K—® Context 的方式。这样一¾U§ä¸€¾U§æž„成了完整çš?Context ½{‰çñ”层次ã€?/p>

æ€ÖM½“来说 ApplicationContext 必须要完成以下几件事åQ?/p>

  • 标识一个应用环å¢?
  • 利用 BeanFactory 创徏 Bean 对象
  • 保存对象关系è¡?
  • 能够捕获各种事äšg

Context ä½œäØ“ Spring çš?Ioc 容器åQŒåŸºæœ¬ä¸Šæ•´åˆäº?Spring 的大部分功能åQŒæˆ–者说是大部分功能的基¼‹€ã€?/p>

Core ¾l„äšg

Core ¾l„äšgä½œäØ“ Spring 的核心组ä»Óž¼Œä»–其中包含了很多的关键类åQŒå…¶ä¸­ä¸€ä¸ªé‡è¦ç»„成部分就是定义了资源的访问方式。这¿UæŠŠæ‰€æœ‰èµ„源都抽象成一个接口的方式很值得在以后的设计中拿来学习。下面就重要看一下这个部分在 Spring 的作用ã€?/p>

下图æ˜?Resource 相关的类¾l“构图:


å›?8. Resource 相关的类¾l“æž„å›?/font>
å›?8. Resource 相关的类¾l“æž„å›? src=

åQˆæŸ¥çœ?å›?8 的清晰版æœ?/font>。)

从上囑֏¯ä»¥çœ‹å‡?Resource 接口ž®è£…了各¿Uå¯èƒ½çš„资源¾cÕdž‹åQŒä¹Ÿž®±æ˜¯å¯¹ä‹É用者来说屏蔽了文äšg¾cÕdž‹çš„不同。对资源的提供者来è¯ß_¼Œå¦‚何把资源包装è“v来交¾l™å…¶ä»–äh用这也是一个问题,我们看到 Resource 接口¾l§æ‰¿äº?InputStreamSource 接口åQŒè¿™ä¸ªæŽ¥å£ä¸­æœ‰ä¸ª getInputStream æ–ÒŽ³•åQŒè¿”回的æ˜? InputStream ¾c…R€‚è¿™æ äh‰€æœ‰çš„资源都被可以通过 InputStream ˜q™ä¸ª¾cÀL¥èŽ·å–åQŒæ‰€ä»¥ä¹Ÿå±è”½äº†èµ„源的提供者。另外还有一个问题就是加载资源的问题åQŒä¹Ÿž®±æ˜¯èµ„源的加载者要¾lŸä¸€åQŒä»Žä¸Šå›¾ä¸­å¯ä»¥çœ‹å‡ø™¿™ä¸ªä“Q务是ç”? ResourceLoader 接口完成åQŒä»–屏蔽了所有的资源加蝲者的差异åQŒåªéœ€è¦å®žçŽ°è¿™ä¸ªæŽ¥å£å°±å¯ä»¥åŠ è²æ‰€æœ‰çš„èµ„æºåQŒä»–的默认实现是 DefaultResourceLoaderã€?/p>

下面看一ä¸?Context å’?Resource 是如何徏立关¾pȝš„åQŸé¦–先看一下他们的¾cÕd…³¾pÕd›¾åQ?/p>
�9. Context �Resource 的类关系�/font>
�9. Context �Resource 的类关系� src=

从上囑֏¯ä»¥çœ‹å‡ºï¼ŒContext 是把资源的加载、解析和描述工作委托¾l™äº† ResourcePatternResolver ¾cÀL¥å®ŒæˆåQŒä»–相当于一个接头ähåQŒä»–把资源的加蝲、解析和资源的定义整合在一起便于其他组件ä‹É用。Core ¾l„äšg中还有很多类似的方式ã€?/p>

Ioc 容器如何工作

前面介绍äº?Core ¾l„äšg、Bean ¾l„äšgå’?Context ¾l„äšgçš„ç»“æž„ä¸Žç›æ€º’关系åQŒä¸‹é¢è¿™é‡Œä»Žä½¿ç”¨è€…角度看一下他们是如何˜qè¡Œçš„,以及我们如何è®?Spring 完成各种功能åQŒSpring 到底能有那些功能åQŒè¿™äº›åŠŸèƒ½æ˜¯å¦‚ä½•å¾—æ¥çš„ï¼Œä¸‹é¢ä»‹ç»ã€?/p>

如何创徏 BeanFactory 工厂

正如å›?2 æè¿°çš„é‚£æ øP¼ŒIoc 容器实际上就æ˜?Context ¾l„äšg¾l“合其他两个¾l„äšg共同构徏了一ä¸?Bean 关系¾|‘,如何构徏˜q™ä¸ªå…³ç³»¾|‘?构徏的入口就åœ?AbstractApplicationContext ¾cȝš„ refresh æ–ÒŽ³•中。这个方法的代码如下åQ?/p>
清单 1. AbstractApplicationContext.refresh
                        public void refresh() throws BeansException, IllegalStateException {
                        synchronized (this.startupShutdownMonitor) {
                        // Prepare this context for refreshing.
                        prepareRefresh();
                        // Tell the subclass to refresh the internal bean factory.
                        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
                        // Prepare the bean factory for use in this context.
                        prepareBeanFactory(beanFactory);
                        try {
                        // Allows post-processing of the bean factory in context subclasses.
                        postProcessBeanFactory(beanFactory);
                        // Invoke factory processors registered as beans in the context.
                        invokeBeanFactoryPostProcessors(beanFactory);
                        // Register bean processors that intercept bean creation.
                        registerBeanPostProcessors(beanFactory);
                        // Initialize message source for this context.
                        initMessageSource();
                        // Initialize event multicaster for this context.
                        initApplicationEventMulticaster();
                        // Initialize other special beans in specific context subclasses.
                        onRefresh();
                        // Check for listener beans and register them.
                        registerListeners();
                        // Instantiate all remaining (non-lazy-init) singletons.
                        finishBeanFactoryInitialization(beanFactory);
                        // Last step: publish corresponding event.
                        finishRefresh();
                        }
                        catch (BeansException ex) {
                        // Destroy already created singletons to avoid dangling resources.
                        destroyBeans();
                        // Reset 'active' flag.
                        cancelRefresh(ex);
                        // Propagate exception to caller.
                        throw ex;
                        }
                        }
                        }
                        

˜q™ä¸ªæ–ÒŽ³•ž®±æ˜¯æž„徏整个 Ioc 容器˜q‡ç¨‹çš„完整的代码åQŒäº†è§£äº†é‡Œé¢çš„æ¯ä¸€è¡Œä»£ç åŸºæœ¬ä¸Šž®×ƒº†è§£å¤§éƒ¨åˆ† Spring 的原理和功能了ã€?/p>

˜q™æ®µä»£ç ä¸»è¦åŒ…含˜q™æ ·å‡ ä¸ªæ­¥éª¤åQ?/p>

  • 构徏 BeanFactoryåQŒä»¥ä¾¿äºŽäº§ç”Ÿæ‰€éœ€çš?#8220;演员”
  • 注册可能感兴­‘£çš„事äšg
  • 创徏 Bean 实例对象
  • 触发被监听的事äšg

下面ž®Þq»“合代码分析这几个˜q‡ç¨‹ã€?/p>

½W¬äºŒä¸‰å¥ž®±æ˜¯åœ¨åˆ›å»ºå’Œé…ç½® BeanFactory。这里是 refresh 也就是刷新配¾|®ï¼Œå‰é¢ä»‹ç»äº?Context 有可更新的子¾c»ï¼Œ˜q™é‡Œæ­£æ˜¯å®žçް˜q™ä¸ªåŠŸèƒ½åQŒå½“ BeanFactory 已存在是ž®±æ›´æ–ŽÍ¼Œå¦‚果没有ž®±æ–°åˆ›å¾ã€‚下面是更新 BeanFactory 的方法代码:


清单 2. AbstractRefreshableApplicationContext. refreshBeanFactory
                        protected final void refreshBeanFactory() throws BeansException {
                        if (hasBeanFactory()) {
                        destroyBeans();
                        closeBeanFactory();
                        }
                        try {
                        DefaultListableBeanFactory beanFactory = createBeanFactory();
                        beanFactory.setSerializationId(getId());
                        customizeBeanFactory(beanFactory);
                        loadBeanDefinitions(beanFactory);
                        synchronized (this.beanFactoryMonitor) {
                        this.beanFactory = beanFactory;
                        }
                        }
                        catch (IOException ex) {
                        throw new ApplicationContextException(
                        "I/O error parsing bean definition source for "
                        + getDisplayName(), ex);
                        }
                        }
                        

˜q™ä¸ªæ–ÒŽ³•实现äº?AbstractApplicationContext 的抽象方æ³? refreshBeanFactoryåQŒè¿™ŒDµä»£ç æ¸…楚的说明äº?BeanFactory çš„åˆ›å»ø™¿‡½E‹ã€‚注æ„?BeanFactory 对象的类型的变化åQŒå‰é¢ä»‹¾läº†ä»–有很多子类åQŒåœ¨ä»€ä¹ˆæƒ…况下使用不同的子¾c»è¿™éžå¸¸å…³é”®ã€‚BeanFactory 的原始对象是 DefaultListableBeanFactoryåQŒè¿™ä¸ªéžå¸¸å…³é”®ï¼Œå› äؓ他设计到后面对这个对象的多种操作åQŒä¸‹é¢çœ‹ä¸€ä¸‹è¿™ä¸ªç±»çš„ç‘ô承层‹Æ¡ç±»å›¾ï¼š


å›?10. DefaultListableBeanFactory ¾cȝ‘ô承关¾pÕd›¾
å›?10. DefaultListableBeanFactory ¾cȝ‘ô承关¾pÕd›¾

åQˆæŸ¥çœ?å›?10 的清晰版æœ?/font>。)

从这个图中发现除äº?BeanFactory 相关的类外,˜q˜å‘çŽîCº†ä¸?Bean çš?register 相关。这åœ? refreshBeanFactory æ–ÒŽ³•中有一è¡?loadBeanDefinitions(beanFactory) ž®†æ‰¾åˆ°ç­”案,˜q™ä¸ªæ–ÒŽ³•ž®†å¼€å§‹åŠ è½½ã€è§£æž?Bean 的定义,也就是把用户定义的数据结构è{åŒ–äØ“ Ioc 容器中的特定数据¾l“æž„ã€?/p>

˜q™ä¸ª˜q‡ç¨‹å¯ä»¥ç”¨ä¸‹é¢æ—¶åºå›¾è§£é‡ŠåQ?/p>
�11. 创徏 BeanFactory 时序�/font>
�11. 创徏 BeanFactory 时序� src=

åQˆæŸ¥çœ?å›?11 的清晰版æœ?/font>。)

Bean 的解析和登记‹¹ç¨‹æ—¶åºå›‘Ö¦‚下:


�12. 解析和登�Bean 对象时序�/font>
�12. 解析和登�Bean 对象时序� src=

åQˆæŸ¥çœ?å›?12 的清晰版æœ?/font>。)

创徏å¥?BeanFactory 后,接下åŽÀL·»åР䏀äº?Spring 本èín需要的一些工å…ïL±»åQŒè¿™ä¸ªæ“ä½œåœ¨ AbstractApplicationContext çš?prepareBeanFactory æ–ÒŽ³•完成ã€?/p>

AbstractApplicationContext 中接下来的三行代码对 Spring 的功能扩展性è“v了至关重要的作用。前两行主要是让你现在可以对已经构徏çš?BeanFactory 的配¾|®åšä¿®æ”¹åQŒåŽé¢ä¸€è¡Œå°±æ˜¯è®©ä½ å¯ä»¥å¯¹ä»¥åŽå†åˆ›å»? Bean 的实例对象时æ·ÕdŠ ä¸€äº›è‡ªå®šä¹‰çš„æ“ä½œã€‚æ‰€ä»¥ä»–ä»¬éƒ½æ˜¯æ‰©å±•äº† Spring 的功能,所以我们要学习使用 Spring 必须对这一部分搞清楚ã€?/p>

其中åœ?invokeBeanFactoryPostProcessors æ–ÒŽ³•中主要是获取实现 BeanFactoryPostProcessor 接口的子¾c…R€‚åÆˆæ‰§è¡Œå®ƒçš„ postProcessBeanFactory æ–ÒŽ³•åQŒè¿™ä¸ªæ–¹æ³•的声明如下åQ?/p>
清单 3. BeanFactoryPostProcessor.postProcessBeanFactory
                        void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
                        throws BeansException;
                        

它的参数æ˜?beanFactoryåQŒè¯´æ˜Žå¯ä»¥å¯¹ beanFactory 做修改,˜q™é‡Œæ³¨æ„˜q™ä¸ª beanFactory æ˜? ConfigurableListableBeanFactory ¾cÕdž‹çš„,˜q™ä¹Ÿå°è¯äº†å‰é¢ä»‹¾lçš„不同 BeanFactory 所使用的场合不同,˜q™é‡Œåªèƒ½æ˜¯å¯é…ç½®çš?BeanFactoryåQŒé˜²æ­¢ä¸€äº›æ•°æ®è¢«ç”¨æˆ·éšæ„ä¿®æ”¹ã€?/p>

registerBeanPostProcessors æ–ÒŽ³•也是可以获取用户定义的实çŽîCº† BeanPostProcessor 接口的子¾c»ï¼Œòq¶æ‰§è¡ŒæŠŠå®ƒä»¬æ³¨å†Œåˆ?BeanFactory 对象中的 beanPostProcessors 变量中。BeanPostProcessor 中声明了两个æ–ÒŽ³•åQšpostProcessBeforeInitialization、postProcessAfterInitialization 分别用于åœ?Bean 对象初始化时执行。可以执行用戯‚‡ªå®šä¹‰çš„æ“ä½œã€?/p>

后面的几行代码是初始化监听事件和对系¾lŸçš„其他监听者的注册åQŒç›‘听者必™åÀL˜¯ ApplicationListener 的子¾c…R€?/p>

如何创徏 Bean 实例òq¶æž„å»?Bean 的关¾pȝ½‘

下面ž®±æ˜¯ Bean 的实例化代码åQŒæ˜¯ä»?finishBeanFactoryInitialization æ–ÒŽ³•开始的ã€?/p>
清单 4. AbstractApplicationContext.finishBeanFactoryInitialization
                        protected void finishBeanFactoryInitialization(
                        ConfigurableListableBeanFactory beanFactory) {
                        // Stop using the temporary ClassLoader for type matching.
                        beanFactory.setTempClassLoader(null);
                        // Allow for caching all bean definition metadata, not expecting further changes.
                        beanFactory.freezeConfiguration();
                        // Instantiate all remaining (non-lazy-init) singletons.
                        beanFactory.preInstantiateSingletons();
                        }
                        

从上面代码中可以发现 Bean 的实例化是在 BeanFactory 中发生的。preInstantiateSingletons æ–ÒŽ³•的代码如下:


清单 5. DefaultListableBeanFactory.preInstantiateSingletons
                        public void preInstantiateSingletons() throws BeansException {
                        if (this.logger.isInfoEnabled()) {
                        this.logger.info("Pre-instantiating singletons in " + this);
                        }
                        synchronized (this.beanDefinitionMap) {
                        for (String beanName : this.beanDefinitionNames) {
                        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
                        if (!bd.isAbstract() && bd.isSingleton()
                        && !bd.isLazyInit()) {
                        if (isFactoryBean(beanName)) {
                        final FactoryBean factory =
                        (FactoryBean) getBean(FACTORY_BEAN_PREFIX+ beanName);
                        boolean isEagerInit;
                        if (System.getSecurityManager() != null
                        && factory instanceof SmartFactoryBean) {
                        isEagerInit = AccessController.doPrivileged(
                        new PrivilegedAction<Boolean>() {
                        public Boolean run() {
                        return ((SmartFactoryBean) factory).isEagerInit();
                        }
                        }, getAccessControlContext());
                        }
                        else {
                        isEagerInit = factory instanceof SmartFactoryBean
                        && ((SmartFactoryBean) factory).isEagerInit();
                        }
                        if (isEagerInit) {
                        getBean(beanName);
                        }
                        }
                        else {
                        getBean(beanName);
                        }
                        }
                        }
                        }
                        }
                        

˜q™é‡Œå‡ºçŽ°äº†ä¸€ä¸ªéžå¸”R‡è¦çš„ Bean —â€?FactoryBeanåQŒå¯ä»¥è¯´ Spring 一大半的扩展的功能都与˜q™ä¸ª Bean 有关åQŒè¿™æ˜¯ä¸ªç‰ÒŽ®Šçš?Bean 他是个工åŽ?BeanåQŒå¯ä»¥äñ”ç”?Bean çš?BeanåQŒè¿™é‡Œçš„产生 Bean 是指 Bean 的实例,如果一个类¾l§æ‰¿ FactoryBean 用户可以自己定义产生实例对象的方法只要实çŽîC»–çš?getObject æ–ÒŽ³•。然而在 Spring 内部˜q™ä¸ª Bean 的实例对象是 FactoryBeanåQŒé€šè¿‡è°ƒç”¨˜q™ä¸ªå¯¹è±¡çš?getObject æ–ÒŽ³•ž®Þpƒ½èŽ·å–ç”¨æˆ·è‡ªå®šä¹‰äñ”生的对象åQŒä»Žè€ŒäØ“ Spring 提供了很好的扩展性。Spring 获取 FactoryBean 本èín的对象是在前面加ä¸?& 来完成的ã€?/p>

如何创徏 Bean 的实例对象以及如何构å»?Bean 实例对象之间的关联关¾pÕd¼ Spring 中的一个核心关键,下面是这个过½E‹çš„‹¹ç¨‹å›¾ã€?/p>
å›?13.Bean 实例创徏‹¹ç¨‹å›?/font>
å›?13.Bean 实例创徏‹¹ç¨‹å›? src=

åQˆæŸ¥çœ?å›?13 的清晰版æœ?/font>。)

如果是普通的 Bean ž®Þq›´æŽ¥åˆ›å»ÞZ»–的实例,是通过调用 getBean æ–ÒŽ³•。下面是创徏 Bean 实例的时序图åQ?/p>
�14.Bean 实例创徏时序�/font>
�14.Bean 实例创徏时序� src=

åQˆæŸ¥çœ?å›?14 的清晰版æœ?/font>。)

˜q˜æœ‰ä¸€ä¸ªéžå¸”R‡è¦çš„部分ž®±æ˜¯å»ºç«‹ Bean 对象实例之间的关¾p»ï¼Œ˜q™ä¹Ÿæ˜?Spring 框架的核心竞争力åQŒä½•时、如何徏立他们之间的关系è¯ïLœ‹ä¸‹é¢çš„æ—¶åºå›¾åQ?/p>
�15.Bean 对象关系建立
�15.Bean 对象关系建立

åQˆæŸ¥çœ?å›?15 的清晰版æœ?/font>。)

Ioc 容器的扩展点

现在˜q˜æœ‰ä¸€ä¸ªé—®é¢˜å°±æ˜¯å¦‚何让˜q™äº› Bean 对象有一定的扩展性,ž®±æ˜¯å¯ä»¥åŠ å…¥ç”¨æˆ·çš„ä¸€äº›æ“ä½œã€‚é‚£ä¹ˆæœ‰å“ªäº›æ‰©å±•ç‚¹å‘¢åQ?Spring 又是如何调用到这些扩展点的?

å¯?Spring çš?Ioc 容器来说åQŒä¸»è¦æœ‰˜q™ä¹ˆå‡ ä¸ªã€‚BeanFactoryPostProcessoråQ? BeanPostProcessor。他们分别是在构å»?BeanFactory 和构å»?Bean 对象时调用。还有就æ˜? InitializingBean å’?DisposableBean 他们分别是在 Bean 实例创徏和销毁时被调用。用户可以实现这些接口中定义的方法,Spring ž®×ƒ¼šåœ¨é€‚当的时候调用他们。还有一个是 FactoryBean 他是个特ŒDŠçš„ BeanåQŒè¿™ä¸?Bean 可以被用æˆäh›´å¤šçš„æŽ§åˆ¶ã€?/p>

˜q™äº›æ‰©å±•炚w€šå¸¸ä¹Ÿæ˜¯æˆ‘们使用 Spring 来完成我们特定ä“Q务的地方åQŒå¦‚何精é€?Spring ž®Þqœ‹ä½ æœ‰æ²¡æœ‰æŽŒæ¡å¥?Spring 有哪些扩展点åQŒåƈ且如何ä‹É用他们,要知道如何ä‹É用他们就必须了解他们内在的机理。可以用下面一个比å–ÀL¥è§£é‡Šã€?/p>

我们æŠ?Ioc 容器比作一个箱子,˜q™ä¸ª½Ž±å­é‡Œæœ‰è‹¥å¹²ä¸ªçƒçš„æ¨¡å­ï¼Œå¯ä»¥ç”¨è¿™äº›æ¨¡å­æ¥é€ å¾ˆå¤šç§ä¸åŒçš„球åQŒè¿˜æœ‰ä¸€ä¸ªé€ è¿™äº›çƒæ¨¡çš„æœºå™¨åQŒè¿™ä¸ªæœºå™¨å¯ä»¥äñ”生球模。那么他们的对应å…? ¾pÕd°±æ˜?BeanFactory ž®±æ˜¯é‚£ä¸ªé€ çƒæ¨¡çš„æœºå™¨åQŒçƒæ¨¡å°±æ˜?BeanåQŒè€Œçƒæ¨¡é€ å‡ºæ¥çš„球就æ˜?Bean 的实例。那前面所说的几个扩展点又在什么地方呢åQ?BeanFactoryPostProcessor 对应到当造球模被造出来时åQŒä½ ž®†æœ‰æœÞZ¼šå¯ä»¥å¯¹å…¶åšå‡ºè®‘Ö½“的修正,也就是他可以帮你修改球模。è€?InitializingBean å’? DisposableBean 是在球模造球的开始和¾l“束阶段åQŒä½ å¯ä»¥å®Œæˆä¸€äº›é¢„备和扫尾工作。BeanPostProcessor ž®±å¯ä»¥è®©ä½ å¯¹çƒæ¨¡é€ å‡ºæ¥çš„球做出适当的修正。最后还有一ä¸? FactoryBeanåQŒå®ƒå¯æ˜¯ä¸€ä¸ªç¥žå¥‡çš„球模。这个球模不是预先就定型了,而是ç”׃½ æ¥ç»™ä»–确定它的åÅžçŠÓž¼Œæ—¢ç„¶ä½ å¯ä»¥ç¡®å®šè¿™ä¸ªçƒæ¨¡åž‹çš„åÅžçŠÓž¼Œå½“然他造出æ? 的球肯定ž®±æ˜¯ä½ æƒ³è¦çš„球了åQŒè¿™æ ·åœ¨˜q™ä¸ª½Ž±å­é‡Œå°¼å¯ä»¥å‘现所有你惌™¦çš„球

Ioc 容器如何为我所�/strong>

前面的介¾läº† Spring å®¹å™¨çš„æž„å»ø™¿‡½E‹ï¼Œé‚?Spring èƒ½äØ“æˆ‘ä»¬åšä»€ä¹ˆï¼ŒSpring çš?Ioc 容器又能做什么呢åQŸæˆ‘们ä‹Éç”? Spring 必须要首先构å»?Ioc 容器åQŒæ²¡æœ‰å®ƒ Spring 无法工作åQŒApplicatonContext.xml ž®±æ˜¯ Ioc 容器的默认配¾|®æ–‡ä»Óž¼ŒSpring 的所有特性功能都是基于这ä¸?Ioc 容器工作的,比如后面要介¾lçš„ AOPã€?/p>

Ioc 它实际上ž®±æ˜¯ä¸ÞZ½ æž„徏了一个魔方,Spring ä¸ÞZ½ æ­å¥½äº†éª¨éª¼æž¶æž„,˜q™ä¸ª™ì”方到底能变å‡ÞZ»€ä¹ˆå¥½çš„东西出来,˜q™å¿…™å»è¦æœ‰ä½ çš„参与。那我们怎么参与åQŸè¿™ž®±æ˜¯å‰é¢è¯´çš„要了è§?Spring 中那有些扩展点,我们通过实现那些扩展ç‚ÒŽ¥æ”¹å˜ Spring çš„é€šç”¨è¡ŒäØ“ã€‚è‡³äºŽå¦‚ä½•å®žçŽ°æ‰©å±•ç‚¹æ¥å¾—åˆ°æˆ‘ä»¬æƒ³è¦çš„ä¸ªæ€§ç»“æžœï¼ŒSpring 中有很多例子åQŒå…¶ä¸?AOP 的实现就æ˜?Spring 本èín实现了其扩展ç‚ÒŽ¥è¾‘Öˆ°äº†å®ƒæƒŒ™¦çš„特性功能,可以拿来参考ã€?/p>


Spring ä¸?AOP ç‰ÒŽ€§è¯¦è§?/strong>

动态代理的实现原理

要了è§?Spring çš?AOP ž®±å¿…™åÕd…ˆäº†è§£çš„动态代理的原理åQŒå› ä¸?AOP ž®±æ˜¯åŸÞZºŽåŠ¨æ€ä»£ç†å®žçŽ°çš„ã€‚åŠ¨æ€ä»£ç†è¿˜è¦ä»Ž JDK 本èín说è“vã€?/p>

åœ?Jdk çš?java.lang.reflect 包下有个 Proxy ¾c»ï¼Œå®ƒæ­£æ˜¯æž„造代理类的入口。这个类的结构入下:


å›?16. Proxy ¾cȝ»“æž?/font>
å›?16. Proxy ¾cȝ»“æž? src=

从上囑֏‘现最后面四个是公有方法。而最后一个方æ³?newProxyInstance ž®±æ˜¯åˆ›å¾ä»£ç†å¯¹è±¡çš„æ–¹æ³•。这个方法的源码如下åQ?/p>
清单 6. Proxy. newProxyInstance
                        public static Object newProxyInstance(ClassLoader loader,
                        Class<?>[] interfaces,
                        InvocationHandler h)
                        throws IllegalArgumentException {
                        if (h == null) {
                        throw new NullPointerException();
                        }
                        Class cl = getProxyClass(loader, interfaces);
                        try {
                        Constructor cons = cl.getConstructor(constructorParams);
                        return (Object) cons.newInstance(new Object[] { h });
                        } catch (NoSuchMethodException e) {
                        throw new InternalError(e.toString());
                        } catch (IllegalAccessException e) {
                        throw new InternalError(e.toString());
                        } catch (InstantiationException e) {
                        throw new InternalError(e.toString());
                        } catch (InvocationTargetException e) {
                        throw new InternalError(e.toString());
                        }
                        }
                        

˜q™ä¸ªæ–ÒŽ³•需要三个参敎ͼšClassLoaderåQŒç”¨äºŽåŠ è½½ä»£ç†ç±»çš?Loader ¾c»ï¼Œé€šå¸¸˜q™ä¸ª Loader 和被代理的类是同一ä¸? Loader ¾c…R€‚InterfacesåQŒæ˜¯è¦è¢«ä»£ç†çš„那些那些接口。InvocationHandleråQŒå°±æ˜¯ç”¨äºŽæ‰§è¡Œé™¤äº†è¢«ä»£ç†æŽ¥å£ä¸­æ–¹æ³•之外的用户自定义的操作åQ? 他也是用户需要代理的最¾lˆç›®çš„。用戯‚°ƒç”¨ç›®æ ‡æ–¹æ³•都被代理到 InvocationHandler ¾cÖM¸­å®šä¹‰çš„唯一æ–ÒŽ³• invoke 中。这在后面再详解ã€?/p>

下面˜q˜æ˜¯çœ‹çœ‹ Proxy 如何产生代理¾cȝš„˜q‡ç¨‹åQŒä»–构造出来的代理¾cÕdˆ°åº•是什么样子?下面揭晓啦ã€?/p>
�17. 创徏代理对象时序�/font>
�17. 创徏代理对象时序� src=

其实从上图中可以发现正在构造代理类的是åœ?ProxyGenerator çš?generateProxyClass 的方法中。ProxyGenerator ¾cÕdœ¨ sun.misc 包下åQŒæ„Ÿå…´è¶£çš„话可以看看他的源码ã€?/p>

假如有这样一个接口,如下åQ?/p>
清单 7. SimpleProxy ¾c?/font>
                        public interface SimpleProxy {
                        public void simpleMethod1();
                        public void simpleMethod2();
                        }
                        

代理来生成的¾cȝ»“构如下:


清单 8. $Proxy2 ¾c?/font>
                        public class $Proxy2 extends java.lang.reflect.Proxy implements SimpleProxy{
                        java.lang.reflect.Method m0;
                        java.lang.reflect.Method m1;
                        java.lang.reflect.Method m2;
                        java.lang.reflect.Method m3;
                        java.lang.reflect.Method m4;
                        int hashCode();
                        boolean equals(java.lang.Object);
                        java.lang.String toString();
                        void simpleMethod1();
                        void simpleMethod2();
                        }
                        

˜q™ä¸ª¾cÖM¸­çš„æ–¹æ³•里面将会是调用 InvocationHandler çš?invoke æ–ÒŽ³•åQŒè€Œæ¯ä¸ªæ–¹æ³•也ž®†å¯¹åº”一个属性变量,˜q™ä¸ªå±žæ€§å˜é‡?m 也将传给 invoke æ–ÒŽ³•中的 Method 参数。整个代理就是这样实现的ã€?/p>

Spring AOP 如何实现

从前面代理的原理我们知道åQŒä»£ç†çš„目的是调用目标方法时我们可以转而执è¡?InvocationHandler ¾cȝš„ invoke æ–ÒŽ³•åQŒæ‰€ä»¥å¦‚何在 InvocationHandler 上做文章ž®±æ˜¯ Spring 实现 Aop 的关键所在ã€?/p>

Spring çš?Aop 实现是遵å®?Aop 联盟的约定。同æ—?Spring 又扩展了它,增加了如 Pointcut、Advisor ½{‰ä¸€äº›æŽ¥å£ä‹É得更加灵‹z…R€?/p>

下面æ˜?Jdk 动态代理的¾cÕd›¾åQ?/p>
å›?18. Jdk 动态代理的¾cÕd›¾
å›?18. Jdk 动态代理的¾cÕd›¾

上图清楚的显½CÞZº† Spring 引用äº?Aop Alliance 定义的接口。姑且不讨论 Spring 如何扩展 Aop AllianceåQŒå…ˆçœ‹çœ‹ Spring 如何实现代理¾cȝš„åQŒè¦å®žçŽ°ä»£ç†¾cÕdœ¨ Spring 的配¾|®æ–‡ä»¶ä¸­é€šå¸¸æ˜¯è¿™æ ·å®šä¸€ä¸?Bean 的,如下åQ?/p>
清单 9. 配置代理¾c?Bean
                        <bean id="testBeanSingleton"
                        class="org.springframework.aop.framework.ProxyFactoryBean">
                        <property name="proxyInterfaces">
                        <value>
                        org.springframework.aop.framework.PrototypeTargetTests$TestBean
                        </value>
                        </property>
                        <property name="target"><ref local="testBeanTarget"></ref> </property>
                        <property name="singleton"><value>true</value></property>
                        <property name="interceptorNames">
                        <list>
                        <value>testInterceptor</value>
                        <value>testInterceptor2</value>
                        </list>
                        </property>
                        </bean>
                        

配置上看到要讄¡½®è¢«ä»£ç†çš„æŽ¥å£åQŒå’ŒæŽ¥å£çš„实现类也就是目标类åQŒä»¥åŠæ‹¦æˆªå™¨ä¹Ÿå°±åœ¨æ‰§è¡Œç›®æ ‡æ–¹æ³•之前被调用åQŒè¿™é‡?Spring 中定义的各种各样的拦截器åQŒå¯ä»¥é€‰æ‹©ä½¿ç”¨ã€?/p>

下面看看 Spring 如何完成了代理以及是如何调用拦截器的�/p>

前面提到 Spring Aop 也是实现其自íw«çš„æ‰©å±•ç‚ÒŽ¥å®Œæˆ˜q™ä¸ªç‰ÒŽ€§çš„åQŒä»Ž˜q™ä¸ªä»£ç†¾cÕd¯ä»¥çœ‹å‡ºå®ƒæ­£æ˜¯¾l§æ‰¿äº?FactoryBean çš? ProxyFactoryBeanåQŒFactoryBean 之所以特别就在它可以让你自定义对象的创徏æ–ÒŽ³•。当然代理对象要通过 Proxy ¾cÀL¥åŠ¨æ€ç”Ÿæˆã€?/p>

下面�Spring 创徏的代理对象的时序图:


å›?19.Spring 代理对象的äñ”ç”?/font>
å›?19.Spring 代理对象的äñ”ç”? src=

Spring 创徏了代理对象后åQŒå½“你调用目标对象上的方法时åQŒå°†éƒ½ä¼šè¢«ä»£ç†åˆ° InvocationHandler ¾cȝš„ invoke æ–ÒŽ³•中执行,˜q™åœ¨å‰é¢å·²ç»è§£é‡Šã€‚在˜q™é‡Œ JdkDynamicAopProxy ¾cÕd®žçŽîCº† InvocationHandler 接口ã€?/p>

下面再看çœ?Spring 是如何调用拦截器的,下面是这个过½E‹çš„æ—¶åºå›¾ï¼š


�20.Spring 调用拦截�/font>
�20.Spring 调用拦截� src=

以上所说的都是 Jdk 动态代理,Spring ˜q˜æ”¯æŒä¸€¿U?CGLIB ¾cÖM»£ç†ï¼Œæ„Ÿå…´­‘£è‡ªå·Þqœ‹å§ã€?/p>


Spring 中设计模式分�/strong>

Spring 中ä‹É用的设计模式也很多,比如工厂模式、单例模式、模版模式等åQŒåœ¨ã€?Webx 框架的系¾lŸæž¶æž„与设计模式》、ã€?Tomcat 的系¾lŸæž¶æž„与模式设计分析》已¾læœ‰ä»‹ç»åQŒè¿™é‡Œå°±ä¸èµ˜˜qîCº†ã€‚这里主要介¾lä»£ç†æ¨¡å¼å’Œ½{–略模式ã€?/p>

代理模式

代理模式原理

代理模式ž®±æ˜¯¾l™æŸä¸€ä¸ªå¯¹è±¡åˆ›å»ÞZ¸€ä¸ªä»£ç†å¯¹è±¡ï¼Œè€Œç”±˜q™ä¸ªä»£ç†å¯¹è±¡æŽ§åˆ¶å¯¹åŽŸå¯¹è±¡çš„å¼•ç”¨ï¼Œè€Œåˆ›å»ø™¿™ä¸ªä»£ç†å¯¹è±¡å°±æ˜¯å¯ä»¥åœ¨è°ƒç”¨åŽŸå¯¹è±¡æ˜¯å¯ä»¥å¢žåŠ ä¸€äº›é¢å¤–çš„æ“ä½œã€‚ä¸‹é¢æ˜¯ä»£ç†æ¨¡å¼çš„ç»“æž„ï¼š


�21. 代理模式的结�/font>
�21. 代理模式的结� src=
  • SubjectåQšæŠ½è±¡ä¸»é¢˜ï¼Œå®ƒæ˜¯ä»£ç†å¯¹è±¡çš„çœŸå®žå¯¹è±¡è¦å®žçŽ°çš„æŽ¥å£ï¼Œå½“ç„¶˜q™å¯ä»¥æ˜¯å¤šä¸ªæŽ¥å£¾l„成ã€?
  • ProxySubjectåQšä»£ç†ç±»é™¤äº†å®žçŽ°æŠ½è±¡ä¸»é¢˜å®šä¹‰çš„æŽ¥å£å¤–åQŒè¿˜å¿…须持有所代理对象的引ç”?
  • RealSubjectåQšè¢«ä»£ç†çš„ç±»åQŒæ˜¯ç›®æ ‡å¯¹è±¡ã€?

Spring 中如何实çŽîC»£ç†æ¨¡å¼?/strong>

Spring Aop ä¸?Jdk 动态代理就是利用代理模式技术实现的。在 Spring 中除了实现被代理对象的接口外åQŒè¿˜ä¼šæœ‰ org.springframework.aop.SpringProxy å’? org.springframework.aop.framework.Advised 两个接口。Spring 中ä‹É用代理模式的¾l“构囑֦‚下:


å›?22. Spring 中ä‹É用代理模式的¾l“æž„å›?/font>
å›?22. Spring 中ä‹É用代理模式的¾l“æž„å›? src=

$Proxy ž®±æ˜¯åˆ›å¾çš„代理对象,è€?Subject 是抽象主题,代理对象是通过 InvocationHandler 来持有对目标对象的引用的ã€?/p>

Spring 中一个真实的代理对象¾l“构如下åQ?/p>
清单 10 代理对象 $Proxy4
                        public class $Proxy4 extends java.lang.reflect.Proxy implements
                        org.springframework.aop.framework.PrototypeTargetTests$TestBean
                        org.springframework.aop.SpringProxy
                        org.springframework.aop.framework.Advised
                        {
                        java.lang.reflect.Method m16;
                        java.lang.reflect.Method m9;
                        java.lang.reflect.Method m25;
                        java.lang.reflect.Method m5;
                        java.lang.reflect.Method m2;
                        java.lang.reflect.Method m23;
                        java.lang.reflect.Method m18;
                        java.lang.reflect.Method m26;
                        java.lang.reflect.Method m6;
                        java.lang.reflect.Method m28;
                        java.lang.reflect.Method m14;
                        java.lang.reflect.Method m12;
                        java.lang.reflect.Method m27;
                        java.lang.reflect.Method m11;
                        java.lang.reflect.Method m22;
                        java.lang.reflect.Method m3;
                        java.lang.reflect.Method m8;
                        java.lang.reflect.Method m4;
                        java.lang.reflect.Method m19;
                        java.lang.reflect.Method m7;
                        java.lang.reflect.Method m15;
                        java.lang.reflect.Method m20;
                        java.lang.reflect.Method m10;
                        java.lang.reflect.Method m1;
                        java.lang.reflect.Method m17;
                        java.lang.reflect.Method m21;
                        java.lang.reflect.Method m0;
                        java.lang.reflect.Method m13;
                        java.lang.reflect.Method m24;
                        int hashCode();
                        int indexOf(org.springframework.aop.Advisor);
                        int indexOf(org.aopalliance.aop.Advice);
                        boolean equals(java.lang.Object);
                        java.lang.String toString();
                        void sayhello();
                        void doSomething();
                        void doSomething2();
                        java.lang.Class getProxiedInterfaces();
                        java.lang.Class getTargetClass();
                        boolean isProxyTargetClass();
                        org.springframework.aop.Advisor; getAdvisors();
                        void addAdvisor(int, org.springframework.aop.Advisor)
                        throws org.springframework.aop.framework.AopConfigException;
                        void addAdvisor(org.springframework.aop.Advisor)
                        throws org.springframework.aop.framework.AopConfigException;
                        void setTargetSource(org.springframework.aop.TargetSource);
                        org.springframework.aop.TargetSource getTargetSource();
                        void setPreFiltered(boolean);
                        boolean isPreFiltered();
                        boolean isInterfaceProxied(java.lang.Class);
                        boolean removeAdvisor(org.springframework.aop.Advisor);
                        void removeAdvisor(int)throws org.springframework.aop.framework.AopConfigException;
                        boolean replaceAdvisor(org.springframework.aop.Advisor,
                        org.springframework.aop.Advisor)
                        throws org.springframework.aop.framework.AopConfigException;
                        void addAdvice(org.aopalliance.aop.Advice)
                        throws org.springframework.aop.framework.AopConfigException;
                        void addAdvice(int, org.aopalliance.aop.Advice)
                        throws org.springframework.aop.framework.AopConfigException;
                        boolean removeAdvice(org.aopalliance.aop.Advice);
                        java.lang.String toProxyConfigString();
                        boolean isFrozen();
                        void setExposeProxy(boolean);
                        boolean isExposeProxy();
                        }
                        

½{–略模式

½{–略模式原理

½{–略模式™å‘֐æ€ä¹‰ž®±æ˜¯åšæŸäº‹çš„½{–ç•¥åQŒè¿™åœ¨ç¼–½E‹ä¸Šé€šå¸¸æ˜¯æŒ‡å®ŒæˆæŸä¸ªæ“ä½œå¯èƒ½æœ‰å¤š¿Uæ–¹æ³•,˜q™äº›æ–ÒŽ³•各有千秋åQŒå¯èƒ½æœ‰ä¸åŒçš„适应的场合,然而这些操作方法都有可能用到。各一个操作方法都当作一个实现策略,使用者可能根据需要选择合适的½{–ç•¥ã€?/p>

下面是策略模式的¾l“æž„åQ?/p>
å›?23. ½{–略模式的结æž?/font>
å›?23. ½{–略模式的结æž? src=

  • ContextåQšä‹É用不同策略的环境åQŒå®ƒå¯ä»¥æ ÒŽ®è‡ªèín的条仉™€‰æ‹©ä¸åŒçš„策略实现类来完成所要的操作。它持有一个策略实例的引用。创建具体策略对象的æ–ÒŽ³•也可以由他完成ã€?
  • StrategyåQšæŠ½è±¡ç­–ç•¥ï¼Œå®šä¹‰æ¯ä¸ª½{–略都要实现的策略方æ³?
  • ConcreteStrategyåQšå…·ä½“策略实现类åQŒå®žçŽ°æŠ½è±¡ç­–ç•¥ä¸­å®šä¹‰çš„ç­–ç•¥æ–¹æ³?

Spring 中策略模式的实现

Spring 中策略模式ä‹É用有多个地方åQŒå¦‚ Bean 定义对象的创å»ÞZ»¥åŠä»£ç†å¯¹è±¡çš„创徏½{‰ã€‚这里主要看一下代理对象创建的½{–略模式的实现ã€?/p>

前面已经了解 Spring 的代理方式有两个 Jdk 动态代理和 CGLIB 代理。这两个代理方式的ä‹É用正是ä‹É用了½{–略模式。它的结构图如下所½Cºï¼š


�24. Spring 中策略模式结构图
�24. Spring 中策略模式结构图

在上面结构图中与标准的策略模式结构稍微有点不同,˜q™é‡ŒæŠ½è±¡½{–ç•¥æ˜?AopProxy 接口åQŒCglib2AopProxy å’? JdkDynamicAopProxy 分别代表两种½{–略的实现方式,ProxyFactoryBean ž®±æ˜¯ä»£è¡¨ Context 角色åQŒå®ƒæ ÒŽ®æ¡äšg选择使用 Jdk 代理方式˜q˜æ˜¯ CGLIB 方式åQŒè€Œå¦å¤–三个类主要是来负责创徏具体½{–略对象åQŒProxyFactoryBean 是通过依赖的方法来兌™”具体½{–略对象的,它是通过调用½{–略对象çš?getProxy(ClassLoader classLoader) æ–ÒŽ³•来完成操作ã€?/p>


æ€È»“

本文通过ä»?Spring 的几个核心组件入手,试图扑ևºæž„徏 Spring 框架的骨骼架构,˜q›è€Œåˆ†æž?Spring 在设计的一些设计理念,是否从中扑ևºä¸€äº›å¥½çš„设计思想åQŒå¯¹æˆ‘们以后½E‹åºè®¾è®¡èƒ½æä¾›ä¸€äº›æ€èµ\。接着再详¾l†åˆ†æžäº† Spring 中是如何实现˜q™äº›ç†å¿µçš„,以及在设计模式上是如何ä‹É用的ã€?/p>

通过分析 Spring ¾l™æˆ‘一个很大的启示ž®±æ˜¯å…¶è¿™å¥—设计理念其实对我们有很强的借鉴意义åQŒå®ƒé€šè¿‡æŠ½è±¡å¤æ‚多变的对象,˜q›ä¸€æ­¥åšè§„范åQŒç„¶åŽæ ¹æ®å®ƒå®šä¹‰çš„这套规范设计出一个容器,容器中构建它们的复杂关系åQŒå…¶å®žçŽ°åœ¨æœ‰å¾ˆå¤šæƒ…å†µéƒ½å¯ä»¥ç”¨˜q™ç§¾cÖM¼¼çš„处理方法ã€?/p>

虽然我很æƒÏxŠŠæˆ‘å¯¹ Spring 的想法完全阐˜q°æ¸…楚,但是所è°?#8220;书不ž®½è¨€åQŒè¨€ä¸å°½æ„ã€?#8221;åQŒæœ‰ä»€ä¹ˆä¸å¯ÒŽˆ–者不清楚的地方大家还是看看其源码吧ã€?/p>

 åŽŸæ–‡åœ°å€ http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/index.html

]]>
Ö÷Õ¾Ö©Öë³ØÄ£°å£º ºÓÔ´ÊÐ| ¼¦¶«ÏØ| ¹ãÖÝÊÐ| ¹È³ÇÏØ| ÄÏÏªÏØ| Ò×ÃÅÏØ| È·É½ÏØ| ľÀï| Ïç³ÇÏØ| ÃÜÔÆÏØ| ÆåÅÆ| Ëɽ­Çø| ¾£ÖÝÊÐ| Âé³ÇÊÐ| ÈýËëÏØ| Îä¶¨ÏØ| Òø´¨ÊÐ| °²ÈûÏØ| Ã×ȪÊÐ| ³¤ÖÎÊÐ| Éñ³ØÏØ| °ÍÇàÏØ| ÚüÖÝÊÐ| ÎÚËÕÊÐ| °ÍÌÁÏØ| °²Í¼ÏØ| бö| ÍÅ·çÏØ| ºÍË¶ÏØ| ºâÑôÏØ| ¸¡É½ÏØ| Çú¸·ÊÐ| ¹ÌÑôÏØ| Т²ýÏØ| ¸»Ô´ÏØ| ÄÏÆ¤ÏØ| ´ó·áÊÐ| µÆËþÊÐ| Ôæ×¯ÊÐ| ãèÂÞÊÐ| ÁÙãðÏØ|