001/* 002 * Copyright 2012-2017 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.boot.context.config; 018 019import java.util.ArrayList; 020import java.util.Collections; 021import java.util.List; 022 023import org.springframework.beans.BeanUtils; 024import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; 025import org.springframework.context.ApplicationContextException; 026import org.springframework.context.ApplicationEvent; 027import org.springframework.context.ApplicationListener; 028import org.springframework.context.event.SimpleApplicationEventMulticaster; 029import org.springframework.core.Ordered; 030import org.springframework.core.annotation.AnnotationAwareOrderComparator; 031import org.springframework.core.env.ConfigurableEnvironment; 032import org.springframework.util.Assert; 033import org.springframework.util.ClassUtils; 034import org.springframework.util.StringUtils; 035 036/** 037 * {@link ApplicationListener} that delegates to other listeners that are specified under 038 * a {@literal context.listener.classes} environment property. 039 * 040 * @author Dave Syer 041 * @author Phillip Webb 042 */ 043public class DelegatingApplicationListener 044 implements ApplicationListener<ApplicationEvent>, Ordered { 045 046 // NOTE: Similar to org.springframework.web.context.ContextLoader 047 048 private static final String PROPERTY_NAME = "context.listener.classes"; 049 050 private int order = 0; 051 052 private SimpleApplicationEventMulticaster multicaster; 053 054 @Override 055 public void onApplicationEvent(ApplicationEvent event) { 056 if (event instanceof ApplicationEnvironmentPreparedEvent) { 057 List<ApplicationListener<ApplicationEvent>> delegates = getListeners( 058 ((ApplicationEnvironmentPreparedEvent) event).getEnvironment()); 059 if (delegates.isEmpty()) { 060 return; 061 } 062 this.multicaster = new SimpleApplicationEventMulticaster(); 063 for (ApplicationListener<ApplicationEvent> listener : delegates) { 064 this.multicaster.addApplicationListener(listener); 065 } 066 } 067 if (this.multicaster != null) { 068 this.multicaster.multicastEvent(event); 069 } 070 } 071 072 @SuppressWarnings("unchecked") 073 private List<ApplicationListener<ApplicationEvent>> getListeners( 074 ConfigurableEnvironment environment) { 075 if (environment == null) { 076 return Collections.emptyList(); 077 } 078 String classNames = environment.getProperty(PROPERTY_NAME); 079 List<ApplicationListener<ApplicationEvent>> listeners = new ArrayList<>(); 080 if (StringUtils.hasLength(classNames)) { 081 for (String className : StringUtils.commaDelimitedListToSet(classNames)) { 082 try { 083 Class<?> clazz = ClassUtils.forName(className, 084 ClassUtils.getDefaultClassLoader()); 085 Assert.isAssignable(ApplicationListener.class, clazz, "class [" 086 + className + "] must implement ApplicationListener"); 087 listeners.add((ApplicationListener<ApplicationEvent>) BeanUtils 088 .instantiateClass(clazz)); 089 } 090 catch (Exception ex) { 091 throw new ApplicationContextException( 092 "Failed to load context listener class [" + className + "]", 093 ex); 094 } 095 } 096 } 097 AnnotationAwareOrderComparator.sort(listeners); 098 return listeners; 099 } 100 101 public void setOrder(int order) { 102 this.order = order; 103 } 104 105 @Override 106 public int getOrder() { 107 return this.order; 108 } 109 110}