All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.dubbo.common.extension.ExtensionDirector Maven / Gradle / Ivy

There is a newer version: 3.3.0-beta.3
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.dubbo.common.extension;

import org.apache.dubbo.rpc.model.ScopeModel;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * ExtensionDirector is a scoped extension loader manager.
 *
 * 

*

ExtensionDirector supports multiple levels, and the child can inherit the parent's extension instances.

*

The way to find and create an extension instance is similar to Java classloader.

*/ public class ExtensionDirector implements ExtensionAccessor { private final ConcurrentMap, ExtensionLoader> extensionLoadersMap = new ConcurrentHashMap<>(64); private final ConcurrentMap, ExtensionScope> extensionScopeMap = new ConcurrentHashMap<>(64); private final ExtensionDirector parent; private final ExtensionScope scope; private final List extensionPostProcessors = new ArrayList<>(); private final ScopeModel scopeModel; private final AtomicBoolean destroyed = new AtomicBoolean(); public ExtensionDirector(ExtensionDirector parent, ExtensionScope scope, ScopeModel scopeModel) { this.parent = parent; this.scope = scope; this.scopeModel = scopeModel; } public void addExtensionPostProcessor(ExtensionPostProcessor processor) { if (!this.extensionPostProcessors.contains(processor)) { this.extensionPostProcessors.add(processor); } } public List getExtensionPostProcessors() { return extensionPostProcessors; } @Override public ExtensionDirector getExtensionDirector() { return this; } @Override @SuppressWarnings("unchecked") public ExtensionLoader getExtensionLoader(Class type) { checkDestroyed(); if (type == null) { throw new IllegalArgumentException("Extension type == null"); } if (!type.isInterface()) { throw new IllegalArgumentException("Extension type (" + type + ") is not an interface!"); } if (!withExtensionAnnotation(type)) { throw new IllegalArgumentException("Extension type (" + type + ") is not an extension, because it is NOT annotated with @" + SPI.class.getSimpleName() + "!"); } // 1. find in local cache ExtensionLoader loader = (ExtensionLoader) extensionLoadersMap.get(type); ExtensionScope scope = extensionScopeMap.get(type); if (scope == null) { SPI annotation = type.getAnnotation(SPI.class); scope = annotation.scope(); extensionScopeMap.put(type, scope); } if (loader == null && scope == ExtensionScope.SELF) { // create an instance in self scope loader = createExtensionLoader0(type); } // 2. find in parent if (loader == null) { if (this.parent != null) { loader = this.parent.getExtensionLoader(type); } } // 3. create it if (loader == null) { loader = createExtensionLoader(type); } return loader; } private ExtensionLoader createExtensionLoader(Class type) { ExtensionLoader loader = null; if (isScopeMatched(type)) { // if scope is matched, just create it loader = createExtensionLoader0(type); } return loader; } @SuppressWarnings("unchecked") private ExtensionLoader createExtensionLoader0(Class type) { checkDestroyed(); ExtensionLoader loader; extensionLoadersMap.putIfAbsent(type, new ExtensionLoader(type, this, scopeModel)); loader = (ExtensionLoader) extensionLoadersMap.get(type); return loader; } private boolean isScopeMatched(Class type) { final SPI defaultAnnotation = type.getAnnotation(SPI.class); return defaultAnnotation.scope().equals(scope); } private static boolean withExtensionAnnotation(Class type) { return type.isAnnotationPresent(SPI.class); } public ExtensionDirector getParent() { return parent; } public void removeAllCachedLoader() { } public void destroy() { if (destroyed.compareAndSet(false, true)) { for (ExtensionLoader extensionLoader : extensionLoadersMap.values()) { extensionLoader.destroy(); } extensionLoadersMap.clear(); extensionScopeMap.clear(); extensionPostProcessors.clear(); } } private void checkDestroyed() { if (destroyed.get()) { throw new IllegalStateException("ExtensionDirector is destroyed"); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy