001/*
002 * Copyright 2002-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 *      https://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.beans.factory.serviceloader;
018
019import java.util.ServiceLoader;
020
021import org.springframework.beans.factory.BeanClassLoaderAware;
022import org.springframework.beans.factory.config.AbstractFactoryBean;
023import org.springframework.lang.Nullable;
024import org.springframework.util.Assert;
025import org.springframework.util.ClassUtils;
026
027/**
028 * Abstract base class for FactoryBeans operating on the
029 * JDK 1.6 {@link java.util.ServiceLoader} facility.
030 *
031 * @author Juergen Hoeller
032 * @since 2.5
033 * @see java.util.ServiceLoader
034 */
035public abstract class AbstractServiceLoaderBasedFactoryBean extends AbstractFactoryBean<Object>
036                implements BeanClassLoaderAware {
037
038        @Nullable
039        private Class<?> serviceType;
040
041        @Nullable
042        private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
043
044
045        /**
046         * Specify the desired service type (typically the service's public API).
047         */
048        public void setServiceType(@Nullable Class<?> serviceType) {
049                this.serviceType = serviceType;
050        }
051
052        /**
053         * Return the desired service type.
054         */
055        @Nullable
056        public Class<?> getServiceType() {
057                return this.serviceType;
058        }
059
060        @Override
061        public void setBeanClassLoader(@Nullable ClassLoader beanClassLoader) {
062                this.beanClassLoader = beanClassLoader;
063        }
064
065
066        /**
067         * Delegates to {@link #getObjectToExpose(java.util.ServiceLoader)}.
068         * @return the object to expose
069         */
070        @Override
071        protected Object createInstance() {
072                Assert.notNull(getServiceType(), "Property 'serviceType' is required");
073                return getObjectToExpose(ServiceLoader.load(getServiceType(), this.beanClassLoader));
074        }
075
076        /**
077         * Determine the actual object to expose for the given ServiceLoader.
078         * <p>Left to concrete subclasses.
079         * @param serviceLoader the ServiceLoader for the configured service class
080         * @return the object to expose
081         */
082        protected abstract Object getObjectToExpose(ServiceLoader<?> serviceLoader);
083
084}