parent
363f6b208d
commit
a248a4b3b4
@ -1,268 +0,0 @@
|
||||
/*
|
||||
* 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.config.spring.beans.factory.annotation;
|
||||
|
||||
import org.apache.dubbo.config.annotation.Reference;
|
||||
import org.apache.dubbo.config.spring.ReferenceBean;
|
||||
import org.apache.dubbo.config.spring.ServiceBean;
|
||||
import org.apache.dubbo.config.spring.context.event.ServiceBeanExportedEvent;
|
||||
import org.apache.dubbo.config.spring.util.AnnotationUtils;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.InjectionMetadata;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.beans.factory.config.BeanPostProcessor} implementation
|
||||
* that Consumer service {@link Reference} annotated fields
|
||||
*
|
||||
* @since 2.5.7
|
||||
*/
|
||||
public class ReferenceAnnotationBeanPostProcessor extends AnnotationInjectedBeanPostProcessor<Reference>
|
||||
implements ApplicationContextAware, ApplicationListener {
|
||||
|
||||
/**
|
||||
* The bean name of {@link ReferenceAnnotationBeanPostProcessor}
|
||||
*/
|
||||
public static final String BEAN_NAME = "referenceAnnotationBeanPostProcessor";
|
||||
|
||||
/**
|
||||
* Cache size
|
||||
*/
|
||||
private static final int CACHE_SIZE = Integer.getInteger(BEAN_NAME + ".cache.size", 32);
|
||||
|
||||
private final ConcurrentMap<String, ReferenceBean<?>> referenceBeanCache =
|
||||
new ConcurrentHashMap<String, ReferenceBean<?>>(CACHE_SIZE);
|
||||
|
||||
private final ConcurrentHashMap<String, ReferenceBeanInvocationHandler> localReferenceBeanInvocationHandlerCache =
|
||||
new ConcurrentHashMap<String, ReferenceBeanInvocationHandler>(CACHE_SIZE);
|
||||
|
||||
private final ConcurrentMap<InjectionMetadata.InjectedElement, ReferenceBean<?>> injectedFieldReferenceBeanCache =
|
||||
new ConcurrentHashMap<InjectionMetadata.InjectedElement, ReferenceBean<?>>(CACHE_SIZE);
|
||||
|
||||
private final ConcurrentMap<InjectionMetadata.InjectedElement, ReferenceBean<?>> injectedMethodReferenceBeanCache =
|
||||
new ConcurrentHashMap<InjectionMetadata.InjectedElement, ReferenceBean<?>>(CACHE_SIZE);
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
/**
|
||||
* Gets all beans of {@link ReferenceBean}
|
||||
*
|
||||
* @return non-null read-only {@link Collection}
|
||||
* @since 2.5.9
|
||||
*/
|
||||
public Collection<ReferenceBean<?>> getReferenceBeans() {
|
||||
return referenceBeanCache.values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get {@link ReferenceBean} {@link Map} in injected field.
|
||||
*
|
||||
* @return non-null {@link Map}
|
||||
* @since 2.5.11
|
||||
*/
|
||||
public Map<InjectionMetadata.InjectedElement, ReferenceBean<?>> getInjectedFieldReferenceBeanMap() {
|
||||
return Collections.unmodifiableMap(injectedFieldReferenceBeanCache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get {@link ReferenceBean} {@link Map} in injected method.
|
||||
*
|
||||
* @return non-null {@link Map}
|
||||
* @since 2.5.11
|
||||
*/
|
||||
public Map<InjectionMetadata.InjectedElement, ReferenceBean<?>> getInjectedMethodReferenceBeanMap() {
|
||||
return Collections.unmodifiableMap(injectedMethodReferenceBeanCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object doGetInjectedBean(Reference reference, Object bean, String beanName, Class<?> injectedType,
|
||||
InjectionMetadata.InjectedElement injectedElement) throws Exception {
|
||||
|
||||
String referencedBeanName = buildReferencedBeanName(reference, injectedType);
|
||||
|
||||
ReferenceBean referenceBean = buildReferenceBeanIfAbsent(referencedBeanName, reference, injectedType, getClassLoader());
|
||||
|
||||
cacheInjectedReferenceBean(referenceBean, injectedElement);
|
||||
|
||||
Object proxy = buildProxy(referencedBeanName, referenceBean, injectedType);
|
||||
|
||||
return proxy;
|
||||
}
|
||||
|
||||
private Object buildProxy(String referencedBeanName, ReferenceBean referenceBean, Class<?> injectedType) {
|
||||
InvocationHandler handler = buildInvocationHandler(referencedBeanName, referenceBean);
|
||||
Object proxy = Proxy.newProxyInstance(getClassLoader(), new Class[]{injectedType}, handler);
|
||||
return proxy;
|
||||
}
|
||||
|
||||
private InvocationHandler buildInvocationHandler(String referencedBeanName, ReferenceBean referenceBean) {
|
||||
|
||||
ReferenceBeanInvocationHandler handler = localReferenceBeanInvocationHandlerCache.get(referencedBeanName);
|
||||
|
||||
if (handler == null) {
|
||||
handler = new ReferenceBeanInvocationHandler(referenceBean);
|
||||
}
|
||||
|
||||
if (applicationContext.containsBean(referencedBeanName)) { // Is local @Service Bean or not ?
|
||||
// ReferenceBeanInvocationHandler's initialization has to wait for current local @Service Bean has been exported.
|
||||
localReferenceBeanInvocationHandlerCache.put(referencedBeanName, handler);
|
||||
} else if (!applicationContext.getBeansOfType(referenceBean.getInterfaceClass()).isEmpty()) { // TODO 芋艿,临时添加,等待官方修复方案
|
||||
localReferenceBeanInvocationHandlerCache.put(referencedBeanName, handler);
|
||||
} else {
|
||||
// Remote Reference Bean should initialize immediately
|
||||
handler.init();
|
||||
}
|
||||
|
||||
return handler;
|
||||
}
|
||||
|
||||
private static class ReferenceBeanInvocationHandler implements InvocationHandler {
|
||||
|
||||
private final ReferenceBean referenceBean;
|
||||
|
||||
private Object bean;
|
||||
|
||||
private ReferenceBeanInvocationHandler(ReferenceBean referenceBean) {
|
||||
this.referenceBean = referenceBean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
Object result = null;
|
||||
try {
|
||||
if (bean == null) { // If the bean is not initialized, invoke init()
|
||||
// issue: https://github.com/apache/incubator-dubbo/issues/3429
|
||||
init();
|
||||
}
|
||||
result = method.invoke(bean, args);
|
||||
} catch (InvocationTargetException e) {
|
||||
// re-throws the actual Exception.
|
||||
throw e.getTargetException();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void init() {
|
||||
this.bean = referenceBean.get();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String buildInjectedObjectCacheKey(Reference reference, Object bean, String beanName,
|
||||
Class<?> injectedType, InjectionMetadata.InjectedElement injectedElement) {
|
||||
|
||||
String key = buildReferencedBeanName(reference, injectedType) +
|
||||
"#source=" + (injectedElement.getMember()) +
|
||||
"#attributes=" + AnnotationUtils.getAttributes(reference,getEnvironment(),true);
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
private String buildReferencedBeanName(Reference reference, Class<?> injectedType) {
|
||||
|
||||
AnnotationBeanNameBuilder builder = AnnotationBeanNameBuilder.create(reference, injectedType);
|
||||
|
||||
builder.environment(getEnvironment());
|
||||
|
||||
return getEnvironment().resolvePlaceholders(builder.build());
|
||||
}
|
||||
|
||||
private ReferenceBean buildReferenceBeanIfAbsent(String referencedBeanName, Reference reference,
|
||||
Class<?> referencedType, ClassLoader classLoader)
|
||||
throws Exception {
|
||||
|
||||
ReferenceBean<?> referenceBean = referenceBeanCache.get(referencedBeanName);
|
||||
|
||||
if (referenceBean == null) {
|
||||
ReferenceBeanBuilder beanBuilder = ReferenceBeanBuilder
|
||||
.create(reference, classLoader, applicationContext)
|
||||
.interfaceClass(referencedType);
|
||||
referenceBean = beanBuilder.build();
|
||||
referenceBeanCache.put(referencedBeanName, referenceBean);
|
||||
}
|
||||
|
||||
return referenceBean;
|
||||
}
|
||||
|
||||
private void cacheInjectedReferenceBean(ReferenceBean referenceBean,
|
||||
InjectionMetadata.InjectedElement injectedElement) {
|
||||
if (injectedElement.getMember() instanceof Field) {
|
||||
injectedFieldReferenceBeanCache.put(injectedElement, referenceBean);
|
||||
} else if (injectedElement.getMember() instanceof Method) {
|
||||
injectedMethodReferenceBeanCache.put(injectedElement, referenceBean);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationEvent event) {
|
||||
if (event instanceof ServiceBeanExportedEvent) {
|
||||
onServiceBeanExportEvent((ServiceBeanExportedEvent) event);
|
||||
} else if (event instanceof ContextRefreshedEvent) {
|
||||
onContextRefreshedEvent((ContextRefreshedEvent) event);
|
||||
}
|
||||
}
|
||||
|
||||
private void onServiceBeanExportEvent(ServiceBeanExportedEvent event) {
|
||||
ServiceBean serviceBean = event.getServiceBean();
|
||||
initReferenceBeanInvocationHandler(serviceBean);
|
||||
}
|
||||
|
||||
private void initReferenceBeanInvocationHandler(ServiceBean serviceBean) {
|
||||
String serviceBeanName = serviceBean.getBeanName();
|
||||
// Remove ServiceBean when it's exported
|
||||
ReferenceBeanInvocationHandler handler = localReferenceBeanInvocationHandlerCache.remove(serviceBeanName);
|
||||
// Initialize
|
||||
if (handler != null) {
|
||||
handler.init();
|
||||
}
|
||||
}
|
||||
|
||||
private void onContextRefreshedEvent(ContextRefreshedEvent event) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
super.destroy();
|
||||
this.referenceBeanCache.clear();
|
||||
this.localReferenceBeanInvocationHandlerCache.clear();
|
||||
this.injectedFieldReferenceBeanCache.clear();
|
||||
this.injectedMethodReferenceBeanCache.clear();
|
||||
}
|
||||
}
|
||||
@ -1,18 +0,0 @@
|
||||
spring:
|
||||
boot:
|
||||
admin:
|
||||
client:
|
||||
enabled: false # 暂时不用了
|
||||
url: http://127.0.0.1:18097
|
||||
|
||||
|
||||
#management:
|
||||
# endpoints:
|
||||
# web:
|
||||
# exposure:
|
||||
# include: "*"
|
||||
# server:
|
||||
# port: 19083 # 配置独立端口。而该端口,不使用 nginx 对外暴露,从而不配置安全认证。也就是说,内网环境可访问,外网环境不可访问。当然,这么做的前提是,认为内网安全。
|
||||
|
||||
swagger:
|
||||
enable: true # 暂时不去掉
|
||||
@ -1,7 +0,0 @@
|
||||
spring:
|
||||
# datasource
|
||||
datasource:
|
||||
url: jdbc:mysql://192.168.88.14:3306/mall_admin?useSSL=false&useUnicode=true&characterEncoding=UTF-8
|
||||
driver-class-name: com.mysql.jdbc.Driver
|
||||
username: root
|
||||
password: ${MALL_MYSQL_PASSWORD}
|
||||
Loading…
Reference in new issue