1 16 17 package org.springframework.context.support; 18 19 import java.io.IOException ; 20 import java.util.ArrayList ; 21 import java.util.Collection ; 22 import java.util.Collections ; 23 import java.util.Date ; 24 import java.util.Iterator ; 25 import java.util.List ; 26 import java.util.Locale ; 27 import java.util.Map ; 28 29 import org.apache.commons.logging.Log; 30 import org.apache.commons.logging.LogFactory; 31 32 import org.springframework.beans.BeansException; 33 import org.springframework.beans.factory.BeanFactory; 34 import org.springframework.beans.factory.DisposableBean; 35 import org.springframework.beans.factory.NoSuchBeanDefinitionException; 36 import org.springframework.beans.factory.config.AutowireCapableBeanFactory; 37 import org.springframework.beans.factory.config.BeanFactoryPostProcessor; 38 import org.springframework.beans.factory.config.BeanPostProcessor; 39 import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; 40 import org.springframework.beans.support.ResourceEditorRegistrar; 41 import org.springframework.context.ApplicationContext; 42 import org.springframework.context.ApplicationContextAware; 43 import org.springframework.context.ApplicationEvent; 44 import org.springframework.context.ApplicationEventPublisherAware; 45 import org.springframework.context.ApplicationListener; 46 import org.springframework.context.ConfigurableApplicationContext; 47 import org.springframework.context.HierarchicalMessageSource; 48 import org.springframework.context.Lifecycle; 49 import org.springframework.context.MessageSource; 50 import org.springframework.context.MessageSourceAware; 51 import org.springframework.context.MessageSourceResolvable; 52 import org.springframework.context.NoSuchMessageException; 53 import org.springframework.context.ResourceLoaderAware; 54 import org.springframework.context.event.ApplicationEventMulticaster; 55 import org.springframework.context.event.ContextClosedEvent; 56 import org.springframework.context.event.ContextRefreshedEvent; 57 import org.springframework.context.event.SimpleApplicationEventMulticaster; 58 import org.springframework.core.OrderComparator; 59 import org.springframework.core.Ordered; 60 import org.springframework.core.io.DefaultResourceLoader; 61 import org.springframework.core.io.Resource; 62 import org.springframework.core.io.support.PathMatchingResourcePatternResolver; 63 import org.springframework.core.io.support.ResourcePatternResolver; 64 import org.springframework.util.Assert; 65 import org.springframework.util.ObjectUtils; 66 67 107 public abstract class AbstractApplicationContext extends DefaultResourceLoader 108 implements ConfigurableApplicationContext, DisposableBean { 109 110 115 public static final String MESSAGE_SOURCE_BEAN_NAME = "messageSource"; 116 117 123 public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster"; 124 125 126 static { 127 ContextClosedEvent.class.getName(); 130 } 131 132 133 134 protected final Log logger = LogFactory.getLog(getClass()); 135 136 137 private ApplicationContext parent; 138 139 140 private final List beanFactoryPostProcessors = new ArrayList (); 141 142 143 private String displayName = ObjectUtils.identityToString(this); 144 145 146 private long startupDate; 147 148 149 private boolean active = false; 150 151 152 private final Object activeMonitor = new Object (); 153 154 155 private final Object startupShutdownMonitor = new Object (); 156 157 158 private Thread shutdownHook; 159 160 161 private ResourcePatternResolver resourcePatternResolver; 162 163 164 private MessageSource messageSource; 165 166 167 private ApplicationEventMulticaster applicationEventMulticaster; 168 169 170 173 public AbstractApplicationContext() { 174 this(null); 175 } 176 177 181 public AbstractApplicationContext(ApplicationContext parent) { 182 this.parent = parent; 183 this.resourcePatternResolver = getResourcePatternResolver(); 184 } 185 186 187 191 195 public ApplicationContext getParent() { 196 return this.parent; 197 } 198 199 204 public AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException { 205 return getBeanFactory(); 206 } 207 208 212 public void setDisplayName(String displayName) { 213 this.displayName = displayName; 214 } 215 216 219 public String getDisplayName() { 220 return this.displayName; 221 } 222 223 226 public long getStartupDate() { 227 return this.startupDate; 228 } 229 230 238 public void publishEvent(ApplicationEvent event) { 239 Assert.notNull(event, "Event must not be null"); 240 if (logger.isDebugEnabled()) { 241 logger.debug("Publishing event in context [" + ObjectUtils.identityToString(this) + "]: " + event); 242 } 243 getApplicationEventMulticaster().multicastEvent(event); 244 if (this.parent != null) { 245 this.parent.publishEvent(event); 246 } 247 } 248 249 254 private ApplicationEventMulticaster getApplicationEventMulticaster() throws IllegalStateException { 255 if (this.applicationEventMulticaster == null) { 256 throw new IllegalStateException ("ApplicationEventMulticaster not initialized - " + 257 "call 'refresh' before multicasting events via the context: " + this); 258 } 259 return this.applicationEventMulticaster; 260 } 261 262 263 267 public void setParent(ApplicationContext parent) { 268 this.parent = parent; 269 } 270 271 public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor beanFactoryPostProcessor) { 272 this.beanFactoryPostProcessors.add(beanFactoryPostProcessor); 273 } 274 275 280 public List getBeanFactoryPostProcessors() { 281 return this.beanFactoryPostProcessors; 282 } 283 284 285 public void refresh() throws BeansException, IllegalStateException { 286 synchronized (this.startupShutdownMonitor) { 287 this.startupDate = System.currentTimeMillis(); 288 289 if (logger.isInfoEnabled()) { 290 logger.info("Refreshing " + this); 291 } 292 293 synchronized (this.activeMonitor) { 294 this.active = true; 295 } 296 297 refreshBeanFactory(); 299 ConfigurableListableBeanFactory beanFactory = getBeanFactory(); 300 301 if (logger.isInfoEnabled()) { 302 logger.info("Bean factory for application context [" + ObjectUtils.identityToString(this) + 303 "]: " + ObjectUtils.identityToString(beanFactory)); 304 } 305 306 beanFactory.setBeanClassLoader(getClassLoader()); 308 309 beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this)); 311 312 beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); 314 beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); 315 beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); 316 beanFactory.ignoreDependencyInterface(MessageSourceAware.class); 317 beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); 318 319 postProcessBeanFactory(beanFactory); 321 322 for (Iterator it = getBeanFactoryPostProcessors().iterator(); it.hasNext();) { 324 BeanFactoryPostProcessor factoryProcessor = (BeanFactoryPostProcessor) it.next(); 325 factoryProcessor.postProcessBeanFactory(beanFactory); 326 } 327 328 if (logger.isDebugEnabled()) { 329 logger.debug(getBeanDefinitionCount() + " beans defined in " + this); 330 } 331 332 try { 333 invokeBeanFactoryPostProcessors(); 335 336 registerBeanPostProcessors(); 338 339 initMessageSource(); 341 342 initApplicationEventMulticaster(); 344 345 onRefresh(); 347 348 registerListeners(); 350 351 beanFactory.preInstantiateSingletons(); 353 354 publishEvent(new ContextRefreshedEvent(this)); 356 } 357 358 catch (BeansException ex) { 359 beanFactory.destroySingletons(); 361 throw ex; 362 } 363 } 364 } 365 366 380 protected ResourcePatternResolver getResourcePatternResolver() { 381 return new PathMatchingResourcePatternResolver(this); 382 } 383 384 392 protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { 393 } 394 395 400 private void invokeBeanFactoryPostProcessors() { 401 String [] factoryProcessorNames = getBeanNamesForType(BeanFactoryPostProcessor.class, true, false); 404 405 List orderedFactoryProcessors = new ArrayList (); 408 List nonOrderedFactoryProcessorNames = new ArrayList (); 409 for (int i = 0; i < factoryProcessorNames.length; i++) { 410 if (isTypeMatch(factoryProcessorNames[i], Ordered.class)) { 411 orderedFactoryProcessors.add(getBean(factoryProcessorNames[i])); 412 } 413 else { 414 nonOrderedFactoryProcessorNames.add(factoryProcessorNames[i]); 415 } 416 } 417 418 Collections.sort(orderedFactoryProcessors, new OrderComparator()); 420 for (Iterator it = orderedFactoryProcessors.iterator(); it.hasNext();) { 421 BeanFactoryPostProcessor factoryProcessor = (BeanFactoryPostProcessor) it.next(); 422 factoryProcessor.postProcessBeanFactory(getBeanFactory()); 423 } 424 for (Iterator it = nonOrderedFactoryProcessorNames.iterator(); it.hasNext();) { 426 String factoryProcessorName = (String ) it.next(); 427 ((BeanFactoryPostProcessor) getBean(factoryProcessorName)).postProcessBeanFactory(getBeanFactory()); 428 } 429 } 430 431 436 private void registerBeanPostProcessors() { 437 String [] processorNames = getBeanNamesForType(BeanPostProcessor.class, true, false); 438 439 int beanProcessorTargetCount = getBeanFactory().getBeanPostProcessorCount() + 1 + processorNames.length; 443 getBeanFactory().addBeanPostProcessor(new BeanPostProcessorChecker(beanProcessorTargetCount)); 444 445 List orderedProcessors = new ArrayList (); 448 List nonOrderedProcessorNames = new ArrayList (); 449 for (int i = 0; i < processorNames.length; i++) { 450 if (isTypeMatch(processorNames[i], Ordered.class)) { 451 orderedProcessors.add(getBean(processorNames[i])); 452 } 453 else { 454 nonOrderedProcessorNames.add(processorNames[i]); 455 } 456 } 457 458 Collections.sort(orderedProcessors, new OrderComparator()); 460 for (Iterator it = orderedProcessors.iterator(); it.hasNext();) { 461 getBeanFactory().addBeanPostProcessor((BeanPostProcessor) it.next()); 462 } 463 for (Iterator it = nonOrderedProcessorNames.iterator(); it.hasNext();) { 465 String processorName = (String ) it.next(); 466 getBeanFactory().addBeanPostProcessor((BeanPostProcessor) getBean(processorName)); 467 } 468 } 469 470 474 private void initMessageSource() { 475 if (containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) { 476 this.messageSource = (MessageSource) getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class); 477 if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) { 479 HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource; 480 if (hms.getParentMessageSource() == null) { 481 hms.setParentMessageSource(getInternalParentMessageSource()); 484 } 485 } 486 if (logger.isDebugEnabled()) { 487 logger.debug("Using MessageSource [" + this.messageSource + "]"); 488 } 489 } 490 else { 491 DelegatingMessageSource dms = new DelegatingMessageSource(); 493 dms.setParentMessageSource(getInternalParentMessageSource()); 494 this.messageSource = dms; 495 if (logger.isDebugEnabled()) { 496 logger.debug("Unable to locate MessageSource with name '" + MESSAGE_SOURCE_BEAN_NAME + 497 "': using default [" + this.messageSource + "]"); 498 } 499 } 500 } 501 502 507 private void initApplicationEventMulticaster() { 508 if (containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) { 509 this.applicationEventMulticaster = (ApplicationEventMulticaster) 510 getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class); 511 if (logger.isDebugEnabled()) { 512 logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]"); 513 } 514 } 515 else { 516 this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(); 517 if (logger.isDebugEnabled()) { 518 logger.debug("Unable to locate ApplicationEventMulticaster with name '" + 519 APPLICATION_EVENT_MULTICASTER_BEAN_NAME + 520 "': using default [" + this.applicationEventMulticaster + "]"); 521 } 522 } 523 } 524 525 531 protected void onRefresh() throws BeansException { 532 } 534 535 539 private void registerListeners() { 540 Collection listeners = getBeansOfType(ApplicationListener.class, true, false).values(); 543 for (Iterator it = listeners.iterator(); it.hasNext();) { 544 addListener((ApplicationListener) it.next()); 545 } 546 } 547 548 553 protected void addListener(ApplicationListener listener) { 554 getApplicationEventMulticaster().addApplicationListener(listener); 555 } 556 557 558 566 public void registerShutdownHook() { 567 if (this.shutdownHook == null) { 568 this.shutdownHook = new Thread () { 570 public void run() { 571 doClose(); 572 } 573 }; 574 Runtime.getRuntime().addShutdownHook(this.shutdownHook); 575 } 576 } 577 578 588 public void destroy() { 589 close(); 590 } 591 592 599 public void close() { 600 synchronized (this.startupShutdownMonitor) { 601 doClose(); 602 if (this.shutdownHook != null) { 605 Runtime.getRuntime().removeShutdownHook(this.shutdownHook); 606 } 607 } 608 } 609 610 619 protected void doClose() { 620 if (isActive()) { 621 if (logger.isInfoEnabled()) { 622 logger.info("Closing " + this); 623 } 624 try { 625 publishEvent(new ContextClosedEvent(this)); 627 } 628 catch (Throwable ex) { 629 logger.error("Exception thrown from ApplicationListener handling ContextClosedEvent", ex); 630 } 631 stop(); 633 destroyBeans(); 635 closeBeanFactory(); 637 onClose(); 638 synchronized (this.activeMonitor) { 639 this.active = false; 640 } 641 } 642 } 643 644 655 protected void destroyBeans() { 656 getBeanFactory().destroySingletons(); 657 } 658 659 667 protected void onClose() { 668 } 670 671 public boolean isActive() { 672 synchronized (this.activeMonitor) { 673 return this.active; 674 } 675 } 676 677 678 682 public Object getBean(String name) throws BeansException { 683 return getBeanFactory().getBean(name); 684 } 685 686 public Object getBean(String name, Class requiredType) throws BeansException { 687 return getBeanFactory().getBean(name, requiredType); 688 } 689 690 public boolean containsBean(String name) { 691 return getBeanFactory().containsBean(name); 692 } 693 694 public boolean isSingleton(String name) throws NoSuchBeanDefinitionException { 695 return getBeanFactory().isSingleton(name); 696 } 697 698 public boolean isPrototype(String name) throws NoSuchBeanDefinitionException { 699 return getBeanFactory().isPrototype(name); 700 } 701 702 public boolean isTypeMatch(String name, Class targetType) throws NoSuchBeanDefinitionException { 703 return getBeanFactory().isTypeMatch(name, targetType); 704 } 705 706 public Class getType(String name) throws NoSuchBeanDefinitionException { 707 return getBeanFactory().getType(name); 708 } 709 710 public String [] getAliases(String name) { 711 return getBeanFactory().getAliases(name); 712 } 713 714 715 719 public boolean containsBeanDefinition(String name) { 720 return getBeanFactory().containsBeanDefinition(name); 721 } 722 723 public int getBeanDefinitionCount() { 724 return getBeanFactory().getBeanDefinitionCount(); 725 } 726 727 public String [] getBeanDefinitionNames() { 728 return getBeanFactory().getBeanDefinitionNames(); 729 } 730 731 public String [] getBeanNamesForType(Class type) { 732 return getBeanFactory().getBeanNamesForType(type); 733 } 734 735 public String [] getBeanNamesForType(Class type, boolean includePrototypes, boolean allowEagerInit) { 736 return getBeanFactory().getBeanNamesForType(type, includePrototypes, allowEagerInit); 737 } 738 739 public Map getBeansOfType(Class type) throws BeansException { 740 return getBeanFactory().getBeansOfType(type); 741 } 742 743 public Map getBeansOfType(Class type, boolean includePrototypes, boolean allowEagerInit) 744 throws BeansException { 745 746 return getBeanFactory().getBeansOfType(type, includePrototypes, allowEagerInit); 747 } 748 749 750 754 public BeanFactory getParentBeanFactory() { 755 return getParent(); 756 } 757 758 public boolean containsLocalBean(String name) { 759 return getBeanFactory().containsLocalBean(name); 760 } 761 762 767 protected BeanFactory getInternalParentBeanFactory() { 768 return (getParent() instanceof ConfigurableApplicationContext) ? 769 ((ConfigurableApplicationContext) getParent()).getBeanFactory() : (BeanFactory) getParent(); 770 } 771 772 773 777 public String getMessage(String code, Object args[], String defaultMessage, Locale locale) { 778 return getMessageSource().getMessage(code, args, defaultMessage, locale); 779 } 780 781 public String getMessage(String code, Object args[], Locale locale) throws NoSuchMessageException { 782 return getMessageSource().getMessage(code, args, locale); 783 } 784 785 public String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException { 786 return getMessageSource().getMessage(resolvable, locale); 787 } 788 789 794 private MessageSource getMessageSource() throws IllegalStateException { 795 if (this.messageSource == null) { 796 throw new IllegalStateException ("MessageSource not initialized - " + 797 "call 'refresh' before accessing messages via the context: " + this); 798 } 799 return this.messageSource; 800 } 801 802 806 protected MessageSource getInternalParentMessageSource() { 807 return (getParent() instanceof AbstractApplicationContext) ? 808 ((AbstractApplicationContext) getParent()).messageSource : getParent(); 809 } 810 811 812 816 public Resource[] getResources(String locationPattern) throws IOException { 817 return this.resourcePatternResolver.getResources(locationPattern); 818 } 819 820 821 825 public void start() { 826 Iterator it = getLifecycleBeans().iterator(); 827 while (it.hasNext()) { 828 Lifecycle lifecycle = (Lifecycle) it.next(); 829 if (!lifecycle.isRunning()) { 830 lifecycle.start(); 831 } 832 } 833 } 834 835 public void stop() { 836 Iterator it = getLifecycleBeans().iterator(); 837 while (it.hasNext()) { 838 Lifecycle lifecycle = (Lifecycle) it.next(); 839 if (lifecycle.isRunning()) { 840 lifecycle.stop(); 841 } 842 } 843 } 844 845 public boolean isRunning() { 846 Iterator it = getLifecycleBeans().iterator(); 847 while (it.hasNext()) { 848 Lifecycle lifecycle = (Lifecycle) it.next(); 849 if (!lifecycle.isRunning()) { 850 return false; 851 } 852 } 853 return true; 854 } 855 856 861 protected Collection getLifecycleBeans() { 862 ConfigurableListableBeanFactory beanFactory = getBeanFactory(); 863 String [] beanNames = beanFactory.getBeanNamesForType(Lifecycle.class, false, false); 864 Collection beans = new ArrayList (beanNames.length); 865 for (int i = 0; i < beanNames.length; i++) { 866 Object bean = beanFactory.getSingleton(beanNames[i]); 867 if (bean != null) { 868 beans.add(bean); 869 } 870 } 871 return beans; 872 } 873 874 875 879 889 protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException ; 890 891 896 protected abstract void closeBeanFactory(); 897 898 911 public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException ; 912 913 914 917 public String toString() { 918 StringBuffer sb = new StringBuffer (ObjectUtils.identityToString(this)); 919 sb.append(": display name [").append(getDisplayName()); 920 sb.append("]; startup date [").append(new Date (getStartupDate())); 921 sb.append("]; "); 922 ApplicationContext parent = getParent(); 923 if (parent == null) { 924 sb.append("root of context hierarchy"); 925 } 926 else { 927 sb.append("parent: ").append(ObjectUtils.identityToString(parent)); 928 } 929 return sb.toString(); 930 } 931 932 933 938 private class BeanPostProcessorChecker implements BeanPostProcessor { 939 940 private final int beanPostProcessorTargetCount; 941 942 public BeanPostProcessorChecker(int beanPostProcessorTargetCount) { 943 this.beanPostProcessorTargetCount = beanPostProcessorTargetCount; 944 } 945 946 public Object postProcessBeforeInitialization(Object bean, String beanName) { 947 return bean; 948 } 949 950 public Object postProcessAfterInitialization(Object bean, String beanName) { 951 if (getBeanFactory().getBeanPostProcessorCount() < this.beanPostProcessorTargetCount) { 952 if (logger.isInfoEnabled()) { 953 logger.info("Bean '" + beanName + "' is not eligible for getting processed by all " + 954 "BeanPostProcessors (for example: not eligible for auto-proxying)"); 955 } 956 } 957 return bean; 958 } 959 } 960 961 } 962 | Popular Tags |