[Spring Boot Project] Merge 3.0.x Spring-Boot project into Dubbo 3.0.x (#7441)

* [Spring Boot Project] Merge 3.0.x Spring-Boot project into Dubbo 3.0.x

* add junit5 dependency

* ignore ut

* change to junit5

* reset ApplicationModel
This commit is contained in:
Albumen Kevin 2021-04-01 15:28:31 +08:00 committed by GitHub
parent 22f5310084
commit be54ec206a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
84 changed files with 7359 additions and 9 deletions

View File

@ -24,11 +24,6 @@ jobs:
- uses: actions/checkout@v2
with:
path: dubbo
- uses: actions/checkout@v2
with:
repository: 'apache/dubbo-spring-boot-project'
ref: ${{env.DUBBO_SPRING_BOOT_REF}}
path: dubbo-spring-boot-project
- uses: actions/setup-java@v1
with:
java-version: 8
@ -46,10 +41,6 @@ jobs:
run: |
cd ./dubbo
./mvnw --batch-mode -U -e --no-transfer-progress clean source:jar install -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -Dmaven.test.skip=true -Dmaven.test.skip.exec=true
- name: "Build Dubbo Spring Boot with Maven"
run: |
cd ./dubbo-spring-boot-project
./mvnw --batch-mode --no-transfer-progress clean source:jar install -Dmaven.test.skip=true -Dmaven.test.skip.exec=true
- name: "Calculate Dubbo Version"
id: dubbo-version
run: |

View File

@ -232,6 +232,32 @@
<artifactId>dubbo-configcenter-nacos</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-actuator</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-autoconfigure</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-actuator-compatible</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-autoconfigure-compatible</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 KiB

View File

@ -0,0 +1,499 @@
# Dubbo Spring Boot Production-Ready
`dubbo-spring-boot-actuator` provides production-ready features (e.g. [health checks](#health-checks), [endpoints](#endpoints), and [externalized configuration](#externalized-configuration)).
## Content
1. [Main Content](https://github.com/apache/dubbo-spring-boot-project)
2. [Integrate with Maven](#integrate-with-maven)
3. [Health Checks](#health-checks)
4. [Endpoints](#endpoints)
5. [Externalized Configuration](#externalized-configuration)
## Integrate with Maven
You can introduce the latest `dubbo-spring-boot-actuator` to your project by adding the following dependency to your pom.xml
```xml
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-actuator</artifactId>
<version>2.7.4.1</version>
</dependency>
```
If your project failed to resolve the dependency, try to add the following repository:
```xml
<repositories>
<repository>
<id>apache.snapshots.https</id>
<name>Apache Development Snapshot Repository</name>
<url>https://repository.apache.org/content/repositories/snapshots</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
```
## Health Checks
`dubbo-spring-boot-actuator` supports the standard Spring Boot `HealthIndicator` as a production-ready feature , which will be aggregated into Spring Boot's `Health` and exported on `HealthEndpoint` that works MVC (Spring Web MVC) and JMX (Java Management Extensions) both if they are available.
### Web Endpoint : `/health`
Suppose a Spring Boot Web application did not specify `management.server.port`, you can access http://localhost:8080/actuator/health via Web Client and will get a response with JSON format is like below :
```json
{
"status": "UP",
"dubbo": {
"status": "UP",
"memory": {
"source": "management.health.dubbo.status.defaults",
"status": {
"level": "OK",
"message": "max:3641M,total:383M,used:92M,free:291M",
"description": null
}
},
"load": {
"source": "management.health.dubbo.status.extras",
"status": {
"level": "OK",
"message": "load:1.73583984375,cpu:8",
"description": null
}
},
"threadpool": {
"source": "management.health.dubbo.status.extras",
"status": {
"level": "OK",
"message": "Pool status:OK, max:200, core:200, largest:0, active:0, task:0, service port: 12345",
"description": null
}
},
"server": {
"source": "dubbo@ProtocolConfig.getStatus()",
"status": {
"level": "OK",
"message": "/192.168.1.103:12345(clients:0)",
"description": null
}
}
}
// ignore others
}
```
`memory`, `load`, `threadpool` and `server` are Dubbo's build-in `StatusChecker`s in above example.
Dubbo allows the application to extend `StatusChecker`'s SPI.
Default , `memory` and `load` will be added into Dubbo's `HealthIndicator` , it could be overridden by
externalized configuration [`StatusChecker`'s defaults](#statuschecker-defaults).
### JMX Endpoint : `Health`
`Health` is a JMX (Java Management Extensions) Endpoint with ObjectName `org.springframework.boot:type=Endpoint,name=Health` , it can be managed by JMX agent ,e.g. JDK tools : `jconsole` and so on.
![](JMX_HealthEndpoint.png)
### Build-in `StatusChecker`s
`META-INF/dubbo/internal/org.apache.dubbo.common.status.StatusChecker` declares Build-in `StatusChecker`s as follow :
```properties
registry=org.apache.dubbo.registry.status.RegistryStatusChecker
spring=org.apache.dubbo.config.spring.status.SpringStatusChecker
datasource=org.apache.dubbo.config.spring.status.DataSourceStatusChecker
memory=org.apache.dubbo.common.status.support.MemoryStatusChecker
load=org.apache.dubbo.common.status.support.LoadStatusChecker
server=org.apache.dubbo.rpc.protocol.dubbo.status.ServerStatusChecker
threadpool=org.apache.dubbo.rpc.protocol.dubbo.status.ThreadPoolStatusChecker
```
The property key that is name of `StatusChecker` can be a valid value of `management.health.dubbo.status.*` in externalized configuration.
## Endpoints
Actuator endpoint `dubbo` supports Actuator Endpoints :
| ID | Enabled | HTTP URI | HTTP Method | Description | Content Type |
| ------------------- | ----------- | ----------------------------------- | ------------------ | ------------------ | ------------------ |
| `dubbo` | `true` | `/actuator/dubbo` | `GET` | Exposes Dubbo's meta data | `application/json` |
| `dubboproperties` | `true` | `/actuator/dubbo/properties` | `GET` | Exposes all Dubbo's Properties | `application/json` |
| `dubboservices` | `false` | `/dubbo/services` | `GET` | Exposes all Dubbo's `ServiceBean` | `application/json` |
| `dubboreferences` | `false` | `/actuator/dubbo/references` | `GET` | Exposes all Dubbo's `ReferenceBean` | `application/json` |
| `dubboconfigs` | `true` | `/actuator/dubbo/configs` | `GET` | Exposes all Dubbo's `*Config` | `application/json` |
| `dubboshutdown` | `false` | `/actuator/dubbo/shutdown` | `POST` | Shutdown Dubbo services | `application/json` |
### Web Endpoints
#### `/actuator/dubbo`
`/dubbo` exposes Dubbo's meta data :
```json
{
"timestamp": 1516623290166,
"versions": {
"dubbo-spring-boot": "2.7.5",
"dubbo": "2.7.5"
},
"urls": {
"dubbo": "https://github.com/apache/dubbo/",
"google-group": "dev@dubbo.apache.org",
"github": "https://github.com/apache/dubbo-spring-boot-project",
"issues": "https://github.com/apache/dubbo-spring-boot-project/issues",
"git": "https://github.com/apache/dubbo-spring-boot-project.git"
}
}
```
###
#### `/actuator/dubbo/properties`
`/actuator/dubbo/properties` exposes all Dubbo's Properties from Spring Boot Externalized Configuration (a.k.a `PropertySources`) :
```json
{
"dubbo.application.id": "dubbo-provider-demo",
"dubbo.application.name": "dubbo-provider-demo",
"dubbo.application.qos-enable": "false",
"dubbo.application.qos-port": "33333",
"dubbo.protocol.id": "dubbo",
"dubbo.protocol.name": "dubbo",
"dubbo.protocol.port": "12345",
"dubbo.registry.address": "N/A",
"dubbo.registry.id": "my-registry",
"dubbo.scan.basePackages": "org.apache.dubbo.spring.boot.sample.provider.service"
}
```
The structure of JSON is simple Key-Value format , the key is property name as and the value is property value.
#### `/actuator/dubbo/services`
`/actuator/dubbo/services` exposes all Dubbo's `ServiceBean` that are declared via `<dubbo:service/>` or `@Service` present in Spring `ApplicationContext` :
```json
{
"ServiceBean@org.apache.dubbo.spring.boot.sample.api.DemoService#defaultDemoService": {
"accesslog": null,
"actives": null,
"cache": null,
"callbacks": null,
"class": "org.apache.dubbo.config.spring.ServiceBean",
"cluster": null,
"connections": null,
"delay": null,
"document": null,
"executes": null,
"export": null,
"exported": true,
"filter": "",
"generic": "false",
"group": null,
"id": "org.apache.dubbo.spring.boot.sample.api.DemoService",
"interface": "org.apache.dubbo.spring.boot.sample.api.DemoService",
"interfaceClass": "org.apache.dubbo.spring.boot.sample.api.DemoService",
"layer": null,
"listener": "",
"loadbalance": null,
"local": null,
"merger": null,
"mock": null,
"onconnect": null,
"ondisconnect": null,
"owner": null,
"path": "org.apache.dubbo.spring.boot.sample.api.DemoService",
"proxy": null,
"retries": null,
"scope": null,
"sent": null,
"stub": null,
"timeout": null,
"token": null,
"unexported": false,
"uniqueServiceName": "org.apache.dubbo.spring.boot.sample.api.DemoService:1.0.0",
"validation": null,
"version": "1.0.0",
"warmup": null,
"weight": null,
"serviceClass": "DefaultDemoService"
}
}
```
The key is the Bean name of `ServiceBean` , `ServiceBean`'s properties compose value.
#### `/actuator/dubbo/references`
`/actuator/dubbo/references` exposes all Dubbo's `ReferenceBean` that are declared via `@Reference` annotating on `Field` or `Method ` :
```json
{
"private org.apache.dubbo.spring.boot.sample.api.DemoService org.apache.dubbo.spring.boot.sample.consumer.controller.DemoConsumerController.demoService": {
"actives": null,
"cache": null,
"callbacks": null,
"class": "org.apache.dubbo.config.spring.ReferenceBean",
"client": null,
"cluster": null,
"connections": null,
"filter": "",
"generic": null,
"group": null,
"id": "org.apache.dubbo.spring.boot.sample.api.DemoService",
"interface": "org.apache.dubbo.spring.boot.sample.api.DemoService",
"interfaceClass": "org.apache.dubbo.spring.boot.sample.api.DemoService",
"layer": null,
"lazy": null,
"listener": "",
"loadbalance": null,
"local": null,
"merger": null,
"mock": null,
"objectType": "org.apache.dubbo.spring.boot.sample.api.DemoService",
"onconnect": null,
"ondisconnect": null,
"owner": null,
"protocol": null,
"proxy": null,
"reconnect": null,
"retries": null,
"scope": null,
"sent": null,
"singleton": true,
"sticky": null,
"stub": null,
"stubevent": null,
"timeout": null,
"uniqueServiceName": "org.apache.dubbo.spring.boot.sample.api.DemoService:1.0.0",
"url": "dubbo://localhost:12345",
"validation": null,
"version": "1.0.0",
"invoker": {
"class": "org.apache.dubbo.common.bytecode.proxy0"
}
}
}
```
The key is the string presentation of `@Reference` `Field` or `Method ` , `ReferenceBean`'s properties compose value.
#### `/actuator/dubbo/configs`
`/actuator/dubbo/configs` exposes all Dubbo's `*Config` :
```json
{
"ApplicationConfig": {
"dubbo-consumer-demo": {
"architecture": null,
"class": "org.apache.dubbo.config.ApplicationConfig",
"compiler": null,
"dumpDirectory": null,
"environment": null,
"id": "dubbo-consumer-demo",
"logger": null,
"name": "dubbo-consumer-demo",
"organization": null,
"owner": null,
"version": null
}
},
"ConsumerConfig": {
},
"MethodConfig": {
},
"ModuleConfig": {
},
"MonitorConfig": {
},
"ProtocolConfig": {
"dubbo": {
"accepts": null,
"accesslog": null,
"buffer": null,
"charset": null,
"class": "org.apache.dubbo.config.ProtocolConfig",
"client": null,
"codec": null,
"contextpath": null,
"dispatcher": null,
"dispather": null,
"exchanger": null,
"heartbeat": null,
"host": null,
"id": "dubbo",
"iothreads": null,
"name": "dubbo",
"networker": null,
"path": null,
"payload": null,
"port": 12345,
"prompt": null,
"queues": null,
"serialization": null,
"server": null,
"status": null,
"telnet": null,
"threadpool": null,
"threads": null,
"transporter": null
}
},
"ProviderConfig": {
},
"ReferenceConfig": {
},
"RegistryConfig": {
},
"ServiceConfig": {
}
}
```
The key is the simple name of Dubbo `*Config` Class , the value is`*Config` Beans' Name-Properties Map.
#### `/actuator/dubbo/shutdown`
`/actuator/dubbo/shutdown` shutdowns Dubbo's components including registries, protocols, services and references :
```json
{
"shutdown.count": {
"registries": 0,
"protocols": 1,
"services": 0,
"references": 1
}
}
```
"shutdown.count" means the count of shutdown of Dubbo's components , and the value indicates how many components have been shutdown.
## Externalized Configuration
### `StatusChecker` Defaults
`management.health.dubbo.status.defaults` is a property name for setting names of `StatusChecker`s , its value is allowed to multiple-values , for example :
```properties
management.health.dubbo.status.defaults = registry,memory,load
```
#### Default Value
The default value is :
```properties
management.health.dubbo.status.defaults = memory,load
```
### `StatusChecker` Extras
`management.health.dubbo.status.extras` is used to override the [ [`StatusChecker`'s defaults]](#statuschecker-defaults) , the multiple-values is delimited by comma :
```properties
management.health.dubbo.status.extras = load,threadpool
```
### Health Checks Enabled
`management.health.dubbo.enabled` is a enabled configuration to turn on or off health checks feature, its' default is `true`.
If you'd like to disable health checks , you chould apply `management.health.dubbo.enabled` to be `false`:
```properties
management.health.dubbo.enabled = false
```
### Endpoints Enabled
Dubbo Spring Boot providers actuator endpoints , however some of them are disable. If you'd like to enable them , please add following properties into externalized configuration :
```properties
# Enables Dubbo All Endpoints
management.endpoint.dubbo.enabled = true
management.endpoint.dubboshutdown.enabled = true
management.endpoint.dubboconfigs.enabled = true
management.endpoint.dubboservices.enabled = true
management.endpoint.dubboreferences.enabled = true
management.endpoint.dubboproperties.enabled = true
```

View File

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dubbo-spring-boot-actuator</artifactId>
<packaging>jar</packaging>
<description>Apache Dubbo Spring Boot Actuator</description>
<dependencies>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-actuator-compatible</artifactId>
<version>${revision}</version>
</dependency>
<!-- Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<optional>true</optional>
</dependency>
<!-- Dubbo autoconfigure -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-autoconfigure</artifactId>
<version>${revision}</version>
</dependency>
<!-- Dubbo -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-common</artifactId>
<version>${revision}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-config-spring</artifactId>
<version>${revision}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-remoting-netty4</artifactId>
<version>${revision}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-serialization-hessian2</artifactId>
<version>${revision}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-rpc-dubbo</artifactId>
<version>${revision}</version>
<optional>true</optional>
</dependency>
<!-- Test Dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-runner</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,88 @@
/*
* 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.spring.boot.actuate.autoconfigure;
import org.apache.dubbo.spring.boot.actuate.endpoint.DubboConfigsMetadataEndpoint;
import org.apache.dubbo.spring.boot.actuate.endpoint.DubboMetadataEndpoint;
import org.apache.dubbo.spring.boot.actuate.endpoint.DubboPropertiesMetadataEndpoint;
import org.apache.dubbo.spring.boot.actuate.endpoint.DubboReferencesMetadataEndpoint;
import org.apache.dubbo.spring.boot.actuate.endpoint.DubboServicesMetadataEndpoint;
import org.apache.dubbo.spring.boot.actuate.endpoint.DubboShutdownEndpoint;
import org.apache.dubbo.spring.boot.actuate.endpoint.condition.CompatibleConditionalOnEnabledEndpoint;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
/**
* Dubbo {@link Endpoint @Endpoint} Auto-{@link Configuration} for Spring Boot Actuator 2.0
*
* @see Endpoint
* @see Configuration
* @since 2.7.0
*/
@Configuration
@PropertySource(
name = "Dubbo Endpoints Default Properties",
value = "classpath:/META-INF/dubbo-endpoints-default.properties")
public class DubboEndpointAnnotationAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@CompatibleConditionalOnEnabledEndpoint
public DubboMetadataEndpoint dubboEndpoint() {
return new DubboMetadataEndpoint();
}
@Bean
@ConditionalOnMissingBean
@CompatibleConditionalOnEnabledEndpoint
public DubboConfigsMetadataEndpoint dubboConfigsMetadataEndpoint() {
return new DubboConfigsMetadataEndpoint();
}
@Bean
@ConditionalOnMissingBean
@CompatibleConditionalOnEnabledEndpoint
public DubboPropertiesMetadataEndpoint dubboPropertiesEndpoint() {
return new DubboPropertiesMetadataEndpoint();
}
@Bean
@ConditionalOnMissingBean
@CompatibleConditionalOnEnabledEndpoint
public DubboReferencesMetadataEndpoint dubboReferencesMetadataEndpoint() {
return new DubboReferencesMetadataEndpoint();
}
@Bean
@ConditionalOnMissingBean
@CompatibleConditionalOnEnabledEndpoint
public DubboServicesMetadataEndpoint dubboServicesMetadataEndpoint() {
return new DubboServicesMetadataEndpoint();
}
@Bean
@ConditionalOnMissingBean
@CompatibleConditionalOnEnabledEndpoint
public DubboShutdownEndpoint dubboShutdownEndpoint() {
return new DubboShutdownEndpoint();
}
}

View File

@ -0,0 +1,43 @@
/*
* 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.spring.boot.actuate.endpoint;
import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.AbstractDubboMetadata;
import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboConfigsMetadata;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import java.util.Map;
/**
* Dubbo Configs Metadata {@link Endpoint}
*
* @since 2.7.0
*/
@Endpoint(id = "dubboconfigs")
public class DubboConfigsMetadataEndpoint extends AbstractDubboMetadata {
@Autowired
private DubboConfigsMetadata dubboConfigsMetadata;
@ReadOperation
public Map<String, Map<String, Map<String, Object>>> configs() {
return dubboConfigsMetadata.configs();
}
}

View File

@ -0,0 +1,44 @@
/*
* 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.spring.boot.actuate.endpoint;
import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboMetadata;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import java.util.Map;
/**
* Actuator {@link Endpoint} to expose Dubbo Meta Data
*
* @see Endpoint
* @since 2.7.0
*/
@Endpoint(id = "dubbo")
public class DubboMetadataEndpoint {
@Autowired
private DubboMetadata dubboMetadata;
@ReadOperation
public Map<String, Object> invoke() {
return dubboMetadata.invoke();
}
}

View File

@ -0,0 +1,43 @@
/*
* 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.spring.boot.actuate.endpoint;
import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.AbstractDubboMetadata;
import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboPropertiesMetadata;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import java.util.SortedMap;
/**
* Dubbo Properties {@link Endpoint}
*
* @since 2.7.0
*/
@Endpoint(id = "dubboproperties")
public class DubboPropertiesMetadataEndpoint extends AbstractDubboMetadata {
@Autowired
private DubboPropertiesMetadata dubboPropertiesMetadata;
@ReadOperation
public SortedMap<String, Object> properties() {
return dubboPropertiesMetadata.properties();
}
}

View File

@ -0,0 +1,44 @@
/*
* 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.spring.boot.actuate.endpoint;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.AbstractDubboMetadata;
import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboReferencesMetadata;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import java.util.Map;
/**
* {@link DubboReference} Metadata {@link Endpoint}
*
* @since 2.7.0
*/
@Endpoint(id = "dubboreferences")
public class DubboReferencesMetadataEndpoint extends AbstractDubboMetadata {
@Autowired
private DubboReferencesMetadata dubboReferencesMetadata;
@ReadOperation
public Map<String, Map<String, Object>> references() {
return dubboReferencesMetadata.references();
}
}

View File

@ -0,0 +1,44 @@
/*
* 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.spring.boot.actuate.endpoint;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.AbstractDubboMetadata;
import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboServicesMetadata;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import java.util.Map;
/**
* {@link DubboService} Metadata {@link Endpoint}
*
* @since 2.7.0
*/
@Endpoint(id = "dubboservices")
public class DubboServicesMetadataEndpoint extends AbstractDubboMetadata {
@Autowired
private DubboServicesMetadata dubboServicesMetadata;
@ReadOperation
public Map<String, Map<String, Object>> services() {
return dubboServicesMetadata.services();
}
}

View File

@ -0,0 +1,44 @@
/*
* 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.spring.boot.actuate.endpoint;
import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.AbstractDubboMetadata;
import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboShutdownMetadata;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.WriteOperation;
import java.util.Map;
/**
* Dubbo Shutdown
*
* @since 2.7.0
*/
@Endpoint(id = "dubboshutdown")
public class DubboShutdownEndpoint extends AbstractDubboMetadata {
@Autowired
private DubboShutdownMetadata dubboShutdownMetadata;
@WriteOperation
public Map<String, Object> shutdown() throws Exception {
return dubboShutdownMetadata.shutdown();
}
}

View File

@ -0,0 +1,51 @@
/*
* 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.spring.boot.actuate.endpoint.condition;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.EndpointExtension;
import org.springframework.context.annotation.Conditional;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* {@link Conditional} that checks whether or not an endpoint is enabled, which is compatible with
* org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint ([2.0.x, 2.2.x])
* org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint
*
* @see CompatibleOnEnabledEndpointCondition
* @since 2.7.7
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Documented
@Conditional(CompatibleOnEnabledEndpointCondition.class)
public @interface CompatibleConditionalOnEnabledEndpoint {
/**
* The endpoint type that should be checked. Inferred when the return type of the
* {@code @Bean} method is either an {@link Endpoint @Endpoint} or an
* {@link EndpointExtension @EndpointExtension}.
*
* @return the endpoint type to check
*/
Class<?> endpoint() default Void.class;
}

View File

@ -0,0 +1,69 @@
/*
* 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.spring.boot.actuate.endpoint.condition;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.util.ClassUtils;
import java.util.stream.Stream;
/**
* {@link Conditional} that checks whether or not an endpoint is enabled, which is compatible with
* org.springframework.boot.actuate.autoconfigure.endpoint.condition.OnEnabledEndpointCondition
* and org.springframework.boot.actuate.autoconfigure.endpoint.condition.OnAvailableEndpointCondition
*
* @see CompatibleConditionalOnEnabledEndpoint
* @since 2.7.7
*/
class CompatibleOnEnabledEndpointCondition implements Condition {
static String[] CONDITION_CLASS_NAMES = {
"org.springframework.boot.actuate.autoconfigure.endpoint.condition.OnAvailableEndpointCondition", // 2.2.0+
"org.springframework.boot.actuate.autoconfigure.endpoint.condition.OnEnabledEndpointCondition" // [2.0.0 , 2.2.x]
};
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
ClassLoader classLoader = context.getClassLoader();
Condition condition = Stream.of(CONDITION_CLASS_NAMES) // Iterate class names
.filter(className -> ClassUtils.isPresent(className, classLoader)) // Search class existing or not by name
.findFirst() // Find the first candidate
.map(className -> ClassUtils.resolveClassName(className, classLoader)) // Resolve class name to Class
.filter(Condition.class::isAssignableFrom) // Accept the Condition implementation
.map(BeanUtils::instantiateClass) // Instantiate Class to be instance
.map(Condition.class::cast) // Cast the instance to be Condition one
.orElse(NegativeCondition.INSTANCE); // Or else get a negative condition
return condition.matches(context, metadata);
}
private static class NegativeCondition implements Condition {
static final NegativeCondition INSTANCE = new NegativeCondition();
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return false;
}
}
}

View File

@ -0,0 +1,21 @@
# Dubbo Endpoints Default Properties is loaded by @PropertySource with low order,
# those values of properties can be override by higher PropertySource
# @see DubboEndpointsAutoConfiguration
# Set enabled for Dubbo Endpoints
management.endpoint.dubbo.enabled = true
management.endpoint.dubboshutdown.enabled = false
management.endpoint.dubboconfigs.enabled = true
management.endpoint.dubboservices.enabled = false
management.endpoint.dubboreferences.enabled = false
management.endpoint.dubboproperties.enabled = true
# "management.endpoints.web.base-path" should not be configured in this file
# Re-defines path-mapping of Dubbo Web Endpoints
management.endpoints.web.path-mapping.dubboshutdown = dubbo/shutdown
management.endpoints.web.path-mapping.dubboconfigs = dubbo/configs
management.endpoints.web.path-mapping.dubboservices = dubbo/services
management.endpoints.web.path-mapping.dubboreferences = dubbo/references
management.endpoints.web.path-mapping.dubboproperties = dubbo/properties

View File

@ -0,0 +1,2 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.apache.dubbo.spring.boot.actuate.autoconfigure.DubboEndpointAnnotationAutoConfiguration

View File

@ -0,0 +1,264 @@
/*
* 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.spring.boot.actuate.autoconfigure;
import org.apache.dubbo.common.BaseServiceMetadata;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.spring.boot.actuate.endpoint.DubboConfigsMetadataEndpoint;
import org.apache.dubbo.spring.boot.actuate.endpoint.DubboMetadataEndpoint;
import org.apache.dubbo.spring.boot.actuate.endpoint.DubboPropertiesMetadataEndpoint;
import org.apache.dubbo.spring.boot.actuate.endpoint.DubboReferencesMetadataEndpoint;
import org.apache.dubbo.spring.boot.actuate.endpoint.DubboServicesMetadataEndpoint;
import org.apache.dubbo.spring.boot.actuate.endpoint.DubboShutdownEndpoint;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Assert;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.web.client.RestTemplate;
import java.util.Map;
import java.util.SortedMap;
import java.util.function.Supplier;
/**
* {@link DubboEndpointAnnotationAutoConfiguration} Test
*
* @since 2.7.0
*/
@ExtendWith(SpringExtension.class)
@SpringBootTest(
classes = {
DubboEndpointAnnotationAutoConfigurationTest.class,
DubboEndpointAnnotationAutoConfigurationTest.ConsumerConfiguration.class
},
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
properties = {
"dubbo.service.version = 1.0.0",
"dubbo.application.id = my-application",
"dubbo.application.name = dubbo-demo-application",
"dubbo.module.id = my-module",
"dubbo.module.name = dubbo-demo-module",
"dubbo.registry.id = my-registry",
"dubbo.registry.address = N/A",
"dubbo.protocol.id=my-protocol",
"dubbo.protocol.name=dubbo",
"dubbo.protocol.port=20880",
"dubbo.provider.id=my-provider",
"dubbo.provider.host=127.0.0.1",
"dubbo.scan.basePackages = org.apache.dubbo.spring.boot.actuate.autoconfigure",
"management.endpoint.dubbo.enabled = true",
"management.endpoint.dubboshutdown.enabled = true",
"management.endpoint.dubboconfigs.enabled = true",
"management.endpoint.dubboservices.enabled = true",
"management.endpoint.dubboreferences.enabled = true",
"management.endpoint.dubboproperties.enabled = true",
"management.endpoints.web.exposure.include = *",
})
@EnableAutoConfiguration
@Disabled
public class DubboEndpointAnnotationAutoConfigurationTest {
@Autowired
private DubboMetadataEndpoint dubboEndpoint;
@Autowired
private DubboConfigsMetadataEndpoint dubboConfigsMetadataEndpoint;
@Autowired
private DubboPropertiesMetadataEndpoint dubboPropertiesEndpoint;
@Autowired
private DubboReferencesMetadataEndpoint dubboReferencesMetadataEndpoint;
@Autowired
private DubboServicesMetadataEndpoint dubboServicesMetadataEndpoint;
@Autowired
private DubboShutdownEndpoint dubboShutdownEndpoint;
private RestTemplate restTemplate = new RestTemplate();
@Autowired
private ObjectMapper objectMapper;
@Value("http://127.0.0.1:${local.management.port}${management.endpoints.web.base-path:/actuator}")
private String actuatorBaseURL;
@BeforeEach
public void init() {
ApplicationModel.reset();
}
@AfterEach
public void destroy() {
ApplicationModel.reset();
}
@Test
public void testShutdown() throws Exception {
Map<String, Object> value = dubboShutdownEndpoint.shutdown();
Map<String, Object> shutdownCounts = (Map<String, Object>) value.get("shutdown.count");
Assert.assertEquals(0, shutdownCounts.get("registries"));
Assert.assertEquals(1, shutdownCounts.get("protocols"));
Assert.assertEquals(1, shutdownCounts.get("services"));
Assert.assertEquals(0, shutdownCounts.get("references"));
}
@Test
public void testConfigs() {
Map<String, Map<String, Map<String, Object>>> configsMap = dubboConfigsMetadataEndpoint.configs();
Map<String, Map<String, Object>> beansMetadata = configsMap.get("ApplicationConfig");
Assert.assertEquals("dubbo-demo-application", beansMetadata.get("my-application").get("name"));
beansMetadata = configsMap.get("ConsumerConfig");
Assert.assertTrue(beansMetadata.isEmpty());
beansMetadata = configsMap.get("MethodConfig");
Assert.assertTrue(beansMetadata.isEmpty());
beansMetadata = configsMap.get("ModuleConfig");
Assert.assertEquals("dubbo-demo-module", beansMetadata.get("my-module").get("name"));
beansMetadata = configsMap.get("MonitorConfig");
Assert.assertTrue(beansMetadata.isEmpty());
beansMetadata = configsMap.get("ProtocolConfig");
Assert.assertEquals("dubbo", beansMetadata.get("my-protocol").get("name"));
beansMetadata = configsMap.get("ProviderConfig");
Assert.assertEquals("127.0.0.1", beansMetadata.get("my-provider").get("host"));
beansMetadata = configsMap.get("ReferenceConfig");
Assert.assertTrue(beansMetadata.isEmpty());
beansMetadata = configsMap.get("RegistryConfig");
Assert.assertEquals("N/A", beansMetadata.get("my-registry").get("address"));
beansMetadata = configsMap.get("ServiceConfig");
Assert.assertFalse(beansMetadata.isEmpty());
}
@Test
public void testServices() {
Map<String, Map<String, Object>> services = dubboServicesMetadataEndpoint.services();
Assert.assertEquals(1, services.size());
Map<String, Object> demoServiceMeta = services.get("ServiceBean:org.apache.dubbo.spring.boot.actuate.autoconfigure.DubboEndpointAnnotationAutoConfigurationTest$DemoService:1.0.0");
Assert.assertEquals("1.0.0", demoServiceMeta.get("version"));
}
@Test
public void testReferences() {
Map<String, Map<String, Object>> references = dubboReferencesMetadataEndpoint.references();
Assert.assertTrue(!references.isEmpty());
String injectedField = "private " + DemoService.class.getName() + " " + ConsumerConfiguration.class.getName() + ".demoService";
Map<String, Object> referenceMap = references.get(injectedField);
Assert.assertNotNull(referenceMap);
Assert.assertEquals(DemoService.class, referenceMap.get("interfaceClass"));
Assert.assertEquals(BaseServiceMetadata.buildServiceKey(DemoService.class.getName(),ConsumerConfiguration.DEMO_GROUP,ConsumerConfiguration.DEMO_VERSION),
referenceMap.get("uniqueServiceName"));
}
@Test
public void testProperties() {
SortedMap<String, Object> properties = dubboPropertiesEndpoint.properties();
Assert.assertEquals("my-application", properties.get("dubbo.application.id"));
Assert.assertEquals("dubbo-demo-application", properties.get("dubbo.application.name"));
Assert.assertEquals("my-module", properties.get("dubbo.module.id"));
Assert.assertEquals("dubbo-demo-module", properties.get("dubbo.module.name"));
Assert.assertEquals("my-registry", properties.get("dubbo.registry.id"));
Assert.assertEquals("N/A", properties.get("dubbo.registry.address"));
Assert.assertEquals("my-protocol", properties.get("dubbo.protocol.id"));
Assert.assertEquals("dubbo", properties.get("dubbo.protocol.name"));
Assert.assertEquals("20880", properties.get("dubbo.protocol.port"));
Assert.assertEquals("my-provider", properties.get("dubbo.provider.id"));
Assert.assertEquals("127.0.0.1", properties.get("dubbo.provider.host"));
Assert.assertEquals("org.apache.dubbo.spring.boot.actuate.autoconfigure", properties.get("dubbo.scan.basePackages"));
}
@Test
public void testHttpEndpoints() throws JsonProcessingException {
// testHttpEndpoint("/dubbo", dubboEndpoint::invoke);
testHttpEndpoint("/dubbo/configs", dubboConfigsMetadataEndpoint::configs);
testHttpEndpoint("/dubbo/services", dubboServicesMetadataEndpoint::services);
testHttpEndpoint("/dubbo/references", dubboReferencesMetadataEndpoint::references);
testHttpEndpoint("/dubbo/properties", dubboPropertiesEndpoint::properties);
}
private void testHttpEndpoint(String actuatorURI, Supplier<Map> resultsSupplier) throws JsonProcessingException {
String actuatorURL = actuatorBaseURL + actuatorURI;
String response = restTemplate.getForObject(actuatorURL, String.class);
Assert.assertEquals(objectMapper.writeValueAsString(resultsSupplier.get()), response);
}
interface DemoService {
String sayHello(String name);
}
@DubboService(
version = "${dubbo.service.version}",
application = "${dubbo.application.id}",
protocol = "${dubbo.protocol.id}",
registry = "${dubbo.registry.id}"
)
static class DefaultDemoService implements DemoService {
public String sayHello(String name) {
return "Hello, " + name + " (from Spring Boot)";
}
}
@Configuration
static class ConsumerConfiguration {
public static final String DEMO_GROUP = "demo";
public static final String DEMO_VERSION = "1.0.0";
@DubboReference(group = DEMO_GROUP, version = DEMO_VERSION)
private DemoService demoService;
}
}

View File

@ -0,0 +1,93 @@
/*
* 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.spring.boot.actuate.endpoint;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.spring.boot.util.DubboUtils;
import org.junit.Assert;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.util.Map;
import static org.apache.dubbo.common.Version.getVersion;
/**
* {@link DubboMetadataEndpoint} Test
*
* @see DubboMetadataEndpoint
* @since 2.7.0
*/
@ExtendWith(SpringExtension.class)
@SpringBootTest(
classes = {
DubboMetadataEndpoint.class
},
properties = {
"dubbo.application.name = dubbo-demo-application"
}
)
@EnableAutoConfiguration
public class DubboEndpointTest {
@Autowired
private DubboMetadataEndpoint dubboEndpoint;
@BeforeEach
public void init() {
ApplicationModel.reset();
}
@AfterEach
public void destroy() {
ApplicationModel.reset();
}
@Test
public void testInvoke() {
Map<String, Object> metadata = dubboEndpoint.invoke();
Assert.assertNotNull(metadata.get("timestamp"));
Map<String, String> versions = (Map<String, String>) metadata.get("versions");
Map<String, String> urls = (Map<String, String>) metadata.get("urls");
Assert.assertFalse(versions.isEmpty());
Assert.assertFalse(urls.isEmpty());
Assert.assertEquals(getVersion(DubboUtils.class, "1.0.0"), versions.get("dubbo-spring-boot"));
Assert.assertEquals(getVersion(), versions.get("dubbo"));
Assert.assertEquals("https://github.com/apache/dubbo", urls.get("dubbo"));
Assert.assertEquals("dev@dubbo.apache.org", urls.get("mailing-list"));
Assert.assertEquals("https://github.com/apache/dubbo-spring-boot-project", urls.get("github"));
Assert.assertEquals("https://github.com/apache/dubbo-spring-boot-project/issues", urls.get("issues"));
Assert.assertEquals("https://github.com/apache/dubbo-spring-boot-project.git", urls.get("git"));
}
}

View File

@ -0,0 +1,225 @@
# Dubbo Spring Boot Auto-Configure
`dubbo-spring-boot-autoconfigure` uses Spring Boot's `@EnableAutoConfiguration` which helps core Dubbo's components to be auto-configured by `DubboAutoConfiguration`. It reduces code, eliminates XML configuration.
## Content
1. [Main Content](https://github.com/apache/dubbo-spring-boot-project)
2. [Integrate with Maven](#integrate-with-maven)
3. [Auto Configuration](#auto-configuration)
4. [Externalized Configuration](#externalized-configuration)
5. [Dubbo Annotation-Driven (Chinese)](http://dubbo.apache.org/zh-cn/blog/dubbo-annotation-driven.html)
6. [Dubbo Externalized Configuration (Chinese)](http://dubbo.apache.org/zh-cn/blog/dubbo-externalized-configuration.html)
## Integrate with Maven
You can introduce the latest `dubbo-spring-boot-autoconfigure` to your project by adding the following dependency to your pom.xml
```xml
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-autoconfigure</artifactId>
<version>2.7.4.1</version>
</dependency>
```
If your project failed to resolve the dependency, try to add the following repository:
```xml
<repositories>
<repository>
<id>apache.snapshots.https</id>
<name>Apache Development Snapshot Repository</name>
<url>https://repository.apache.org/content/repositories/snapshots</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
```
## Auto Configuration
Since `2.5.7` , Dubbo totally supports Annotation-Driven , core Dubbo's components that are registered and initialized in Spring application context , including exterialized configuration features. However , those features need to trigger in manual configuration , e.g `@DubboComponentScan` , `@EnableDubboConfig` or `@EnableDubbo`.
> If you'd like to learn more , please read [Dubbo Annotation-Driven (Chinese)](http://dubbo.apache.org/zh-cn/blog/dubbo-annotation-driven.html)
`dubbo-spring-boot-autoconfigure` uses Spring Boot's `@EnableAutoConfiguration` which helps core Dubbo's components to be auto-configured by `DubboAutoConfiguration`. It reduces code, eliminates XML configuration.
## Externalized Configuration
Externalized Configuration is a core feature of Spring Boot , Dubbo Spring Boot not only supports it definitely , but also inherits Dubbo's Externalized Configuration, thus it provides single and multiple Dubbo's `*Config` Bindings from `PropertySources` , and `"dubbo."` is a common prefix of property name.
> If you'd like to learn more , please read [Dubbo Externalized Configuration](http://dubbo.apache.org/zh-cn/blog/dubbo-externalized-configuration.html)(Chinese).
### Single Dubbo Config Bean Bindings
In most use scenarios , "Single Dubbo Config Bean Bindings" is enough , because a Dubbo application only requires single Bean of `*Config` (e.g `ApplicationConfig`). You add properties in `application.properties` to configure Dubbo's `*Config` Beans that you want , be like this :
```properties
dubbo.application.name = foo
dubbo.application.owner = bar
dubbo.registry.address = 10.20.153.10:9090
```
There are two Spring Beans will be initialized when Spring `ApplicatonContext` is ready, their Bean types are `ApplicationConfig` and `RegistryConfig`.
#### Getting Single Dubbo Config Bean
If application requires current `ApplicationConfig` Bean in somewhere , you can get it from Spring `BeanFactory` as those code :
```java
BeanFactory beanFactory = ....
ApplicationConfig applicationConfig = beanFactory.getBean(ApplicationConfig.class)
```
or inject it :
```java
@Autowired
private ApplicationConfig application;
```
#### Identifying Single Dubbo Config Bean
If you'd like to identify this `ApplicationConfig` Bean , you could add **"id"** property:
```properties
dubbo.application.id = application-bean-id
```
#### Mapping Single Dubbo Config Bean
The whole Properties Mapping of "Single Dubbo Config Bean Bindings" lists below :
| Dubbo `*Config` Type | The prefix of property name for Single Bindings |
| -------------------- | ---------------------------------------- |
| `ProtocolConfig` | `dubbo.protocol` |
| `ApplicationConfig` | `dubbo.application` |
| `ModuleConfig` | `dubbo.module` |
| `RegistryConfig` | `dubbo.registry` |
| `MonitorConfig` | `dubbo.monitor` |
| `ProviderConfig` | `dubbo.provider` |
| `ConsumerConfig` | `dubbo.consumer` |
An example properties :
```properties
# Single Dubbo Config Bindings
## ApplicationConfig
dubbo.application.id = applicationBean
dubbo.application.name = dubbo-demo-application
## ModuleConfig
dubbo.module.id = moduleBean
dubbo.module.name = dubbo-demo-module
## RegistryConfig
dubbo.registry.address = zookeeper://192.168.99.100:32770
## ProtocolConfig
dubbo.protocol.name = dubbo
dubbo.protocol.port = 20880
## MonitorConfig
dubbo.monitor.address = zookeeper://127.0.0.1:32770
## ProviderConfig
dubbo.provider.host = 127.0.0.1
## ConsumerConfig
dubbo.consumer.client = netty
```
### Multiple Dubbo Config Bean Bindings
In contrast , "Multiple Dubbo Config Bean Bindings" means Externalized Configuration will be used to configure multiple Dubbo `*Config` Beans.
#### Getting Multiple Dubbo Config Bean
The whole Properties Mapping of "Multiple Dubbo Config Bean Bindings" lists below :
| Dubbo `*Config` Type | The prefix of property name for Multiple Bindings |
| -------------------- | ---------------------------------------- |
| `ProtocolConfig` | `dubbo.protocols` |
| `ApplicationConfig` | `dubbo.applications` |
| `ModuleConfig` | `dubbo.modules` |
| `RegistryConfig` | `dubbo.registries` |
| `MonitorConfig` | `dubbo.monitors` |
| `ProviderConfig` | `dubbo.providers` |
| `ConsumerConfig` | `dubbo.consumers` |
#### Identifying Multiple Dubbo Config Bean
There is a different way to identify Multiple Dubbo Config Bean , the configuration pattern is like this :
`${config-property-prefix}.${config-bean-id}.${property-name} = some value` , let's explain those placehoders :
- `${config-property-prefix}` : The The prefix of property name for Multiple Bindings , e.g. `dubbo.protocols`, `dubbo.applications` and so on.
- `${config-bean-id}` : The bean id of Dubbo's `*Config`
- `${property-name}`: The property name of `*Config`
An example properties :
```properties
dubbo.applications.application1.name = dubbo-demo-application
dubbo.applications.application2.name = dubbo-demo-application2
dubbo.modules.module1.name = dubbo-demo-module
dubbo.registries.registry1.address = zookeeper://192.168.99.100:32770
dubbo.protocols.protocol1.name = dubbo
dubbo.protocols.protocol1.port = 20880
dubbo.monitors.monitor1.address = zookeeper://127.0.0.1:32770
dubbo.providers.provider1.host = 127.0.0.1
dubbo.consumers.consumer1.client = netty
```
### IDE Support
If you used advanced IDE tools , for instance [Jetbrains IDEA Ultimate](https://www.jetbrains.com/idea/) develops Dubbo Spring Boot application, it will popup the tips of Dubbo Configuration Bindings in `application.properties` :
#### Case 1 - Single Bindings
![](config-popup-window.png)
#### Case 2 - Mutiple Bindings
![](mconfig-popup-window.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

View File

@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dubbo-spring-boot-autoconfigure</artifactId>
<packaging>jar</packaging>
<description>Apache Dubbo Spring Boot Auto-Configure</description>
<dependencies>
<!-- Spring Boot Auto-Configuration -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-autoconfigure-compatible</artifactId>
<version>${revision}</version>
</dependency>
<!-- Spring Boot dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
<optional>true</optional>
</dependency>
<!-- Dubbo -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-common</artifactId>
<version>${revision}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-config-spring</artifactId>
<version>${revision}</version>
<optional>true</optional>
</dependency>
<!-- Test Dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,79 @@
/*
* 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.spring.boot.autoconfigure;
import org.apache.dubbo.config.spring.context.properties.DubboConfigBinder;
import com.alibaba.spring.context.config.ConfigurationBeanBinder;
import org.springframework.boot.context.properties.bind.BindHandler;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.bind.PropertySourcesPlaceholdersResolver;
import org.springframework.boot.context.properties.bind.handler.IgnoreErrorsBindHandler;
import org.springframework.boot.context.properties.bind.handler.NoUnboundElementsBindHandler;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
import org.springframework.boot.context.properties.source.UnboundElementsSourceFilter;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.PropertySource;
import java.util.Map;
import static java.util.Arrays.asList;
import static org.springframework.boot.context.properties.source.ConfigurationPropertySources.from;
/**
* Spring Boot Relaxed {@link DubboConfigBinder} implementation
* see org.springframework.boot.context.properties.ConfigurationPropertiesBinder
*
* @since 2.7.0
*/
class BinderDubboConfigBinder implements ConfigurationBeanBinder {
@Override
public void bind(Map<String, Object> configurationProperties, boolean ignoreUnknownFields,
boolean ignoreInvalidFields, Object configurationBean) {
Iterable<PropertySource<?>> propertySources = asList(new MapPropertySource("internal", configurationProperties));
// Converts ConfigurationPropertySources
Iterable<ConfigurationPropertySource> configurationPropertySources = from(propertySources);
// Wrap Bindable from DubboConfig instance
Bindable bindable = Bindable.ofInstance(configurationBean);
Binder binder = new Binder(configurationPropertySources, new PropertySourcesPlaceholdersResolver(propertySources));
// Get BindHandler
BindHandler bindHandler = getBindHandler(ignoreUnknownFields, ignoreInvalidFields);
// Bind
binder.bind("", bindable, bindHandler);
}
private BindHandler getBindHandler(boolean ignoreUnknownFields,
boolean ignoreInvalidFields) {
BindHandler handler = BindHandler.DEFAULT;
if (ignoreInvalidFields) {
handler = new IgnoreErrorsBindHandler(handler);
}
if (!ignoreUnknownFields) {
UnboundElementsSourceFilter filter = new UnboundElementsSourceFilter();
handler = new NoUnboundElementsBindHandler(handler, filter);
}
return handler;
}
}

View File

@ -0,0 +1,92 @@
/*
* 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.spring.boot.autoconfigure;
import com.alibaba.spring.context.config.ConfigurationBeanBinder;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.core.env.AbstractEnvironment;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertyResolver;
import java.util.Map;
import java.util.Set;
import static com.alibaba.spring.util.PropertySourcesUtils.getSubProperties;
import static java.util.Collections.emptySet;
import static org.apache.dubbo.spring.boot.util.DubboUtils.BASE_PACKAGES_BEAN_NAME;
import static org.apache.dubbo.spring.boot.util.DubboUtils.BASE_PACKAGES_PROPERTY_NAME;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_PREFIX;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_SCAN_PREFIX;
import static org.apache.dubbo.spring.boot.util.DubboUtils.RELAXED_DUBBO_CONFIG_BINDER_BEAN_NAME;
import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE;
/**
* Dubbo Relaxed Binding Auto-{@link Configuration} for Spring Boot 2.0
*
* @see DubboRelaxedBindingAutoConfiguration
* @since 2.7.0
*/
@Configuration
@ConditionalOnProperty(prefix = DUBBO_PREFIX, name = "enabled", matchIfMissing = true)
@ConditionalOnClass(name = "org.springframework.boot.context.properties.bind.Binder")
@AutoConfigureBefore(DubboRelaxedBindingAutoConfiguration.class)
public class DubboRelaxedBinding2AutoConfiguration {
public PropertyResolver dubboScanBasePackagesPropertyResolver(ConfigurableEnvironment environment) {
ConfigurableEnvironment propertyResolver = new AbstractEnvironment() {
@Override
protected void customizePropertySources(MutablePropertySources propertySources) {
Map<String, Object> dubboScanProperties = getSubProperties(environment.getPropertySources(), DUBBO_SCAN_PREFIX);
propertySources.addLast(new MapPropertySource("dubboScanProperties", dubboScanProperties));
}
};
ConfigurationPropertySources.attach(propertyResolver);
return propertyResolver;
}
/**
* The bean is used to scan the packages of Dubbo Service classes
*
* @param environment {@link Environment} instance
* @return non-null {@link Set}
* @since 2.7.8
*/
@ConditionalOnMissingBean(name = BASE_PACKAGES_BEAN_NAME)
@Bean(name = BASE_PACKAGES_BEAN_NAME)
public Set<String> dubboBasePackages(ConfigurableEnvironment environment) {
PropertyResolver propertyResolver = dubboScanBasePackagesPropertyResolver(environment);
return propertyResolver.getProperty(BASE_PACKAGES_PROPERTY_NAME, Set.class, emptySet());
}
@ConditionalOnMissingBean(name = RELAXED_DUBBO_CONFIG_BINDER_BEAN_NAME, value = ConfigurationBeanBinder.class)
@Bean(RELAXED_DUBBO_CONFIG_BINDER_BEAN_NAME)
@Scope(scopeName = SCOPE_PROTOTYPE)
public ConfigurationBeanBinder relaxedDubboConfigBinder() {
return new BinderDubboConfigBinder();
}
}

View File

@ -0,0 +1,2 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.apache.dubbo.spring.boot.autoconfigure.DubboRelaxedBinding2AutoConfiguration

View File

@ -0,0 +1,72 @@
/*
* 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.spring.boot.autoconfigure;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.RegistryConfig;
import com.alibaba.spring.context.config.ConfigurationBeanBinder;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Map;
import static com.alibaba.spring.util.PropertySourcesUtils.getSubProperties;
/**
* {@link BinderDubboConfigBinder} Test
*
* @since 2.7.0
*/
@RunWith(SpringRunner.class)
@TestPropertySource(locations = "classpath:/dubbo.properties")
@ContextConfiguration(classes = BinderDubboConfigBinder.class)
public class BinderDubboConfigBinderTest {
@Autowired
private ConfigurationBeanBinder dubboConfigBinder;
@Autowired
private ConfigurableEnvironment environment;
@Test
public void testBinder() {
ApplicationConfig applicationConfig = new ApplicationConfig();
Map<String, Object> properties = getSubProperties(environment.getPropertySources(), "dubbo.application");
dubboConfigBinder.bind(properties, true, true, applicationConfig);
Assert.assertEquals("hello", applicationConfig.getName());
Assert.assertEquals("world", applicationConfig.getOwner());
RegistryConfig registryConfig = new RegistryConfig();
properties = getSubProperties(environment.getPropertySources(), "dubbo.registry");
dubboConfigBinder.bind(properties, true, true, registryConfig);
Assert.assertEquals("10.20.153.17", registryConfig.getAddress());
ProtocolConfig protocolConfig = new ProtocolConfig();
properties = getSubProperties(environment.getPropertySources(), "dubbo.protocol");
dubboConfigBinder.bind(properties, true, true, protocolConfig);
Assert.assertEquals(Integer.valueOf(20881), protocolConfig.getPort());
}
}

View File

@ -0,0 +1,94 @@
/*
* 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.spring.boot.autoconfigure;
import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor;
import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceClassPostProcessor;
import com.alibaba.spring.context.config.ConfigurationBeanBinder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.ClassUtils;
import java.util.Map;
import java.util.Set;
import static org.apache.dubbo.spring.boot.util.DubboUtils.BASE_PACKAGES_BEAN_NAME;
import static org.apache.dubbo.spring.boot.util.DubboUtils.RELAXED_DUBBO_CONFIG_BINDER_BEAN_NAME;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
* {@link DubboRelaxedBinding2AutoConfiguration} Test
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = DubboRelaxedBinding2AutoConfigurationTest.class, properties = {
"dubbo.scan.basePackages = org.apache.dubbo.spring.boot.autoconfigure"
})
@EnableAutoConfiguration
@PropertySource(value = "classpath:/dubbo.properties")
public class DubboRelaxedBinding2AutoConfigurationTest {
@Autowired
@Qualifier(BASE_PACKAGES_BEAN_NAME)
private Set<String> packagesToScan;
@Autowired
@Qualifier(RELAXED_DUBBO_CONFIG_BINDER_BEAN_NAME)
private ConfigurationBeanBinder dubboConfigBinder;
@Autowired
private ObjectProvider<ServiceClassPostProcessor> serviceClassPostProcessor;
@Autowired
private ObjectProvider<ReferenceAnnotationBeanPostProcessor> referenceAnnotationBeanPostProcessor;
@Autowired
private Environment environment;
@Autowired
private Map<String, Environment> environments;
@Test
public void testBeans() {
assertTrue(ClassUtils.isAssignableValue(BinderDubboConfigBinder.class, dubboConfigBinder));
assertNotNull(serviceClassPostProcessor);
assertNotNull(serviceClassPostProcessor.getIfAvailable());
assertNotNull(referenceAnnotationBeanPostProcessor);
assertNotNull(referenceAnnotationBeanPostProcessor.getIfAvailable());
assertNotNull(environment);
assertNotNull(environments);
assertEquals(1, environments.size());
assertTrue(environments.containsValue(environment));
}
}

View File

@ -0,0 +1,97 @@
/*
* 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.spring.boot.env;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.boot.SpringApplication;
import org.springframework.core.Ordered;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import org.springframework.mock.env.MockEnvironment;
import java.util.HashMap;
/**
* {@link DubboDefaultPropertiesEnvironmentPostProcessor} Test
*/
public class DubboDefaultPropertiesEnvironmentPostProcessorTest {
private DubboDefaultPropertiesEnvironmentPostProcessor instance =
new DubboDefaultPropertiesEnvironmentPostProcessor();
private SpringApplication springApplication = new SpringApplication();
@Test
public void testOrder() {
Assert.assertEquals(Ordered.LOWEST_PRECEDENCE, instance.getOrder());
}
@Test
public void testPostProcessEnvironment() {
MockEnvironment environment = new MockEnvironment();
// Case 1 : Not Any property
instance.postProcessEnvironment(environment, springApplication);
// Get PropertySources
MutablePropertySources propertySources = environment.getPropertySources();
// Nothing to change
PropertySource defaultPropertySource = propertySources.get("defaultProperties");
Assert.assertNotNull(defaultPropertySource);
Assert.assertEquals("true", defaultPropertySource.getProperty("dubbo.config.multiple"));
Assert.assertEquals("false", defaultPropertySource.getProperty("dubbo.application.qos-enable"));
// Case 2 : Only set property "spring.application.name"
environment.setProperty("spring.application.name", "demo-dubbo-application");
instance.postProcessEnvironment(environment, springApplication);
defaultPropertySource = propertySources.get("defaultProperties");
Object dubboApplicationName = defaultPropertySource.getProperty("dubbo.application.name");
Assert.assertEquals("demo-dubbo-application", dubboApplicationName);
// Case 3 : Only set property "dubbo.application.name"
// Rest environment
environment = new MockEnvironment();
propertySources = environment.getPropertySources();
environment.setProperty("dubbo.application.name", "demo-dubbo-application");
instance.postProcessEnvironment(environment, springApplication);
defaultPropertySource = propertySources.get("defaultProperties");
Assert.assertNotNull(defaultPropertySource);
dubboApplicationName = environment.getProperty("dubbo.application.name");
Assert.assertEquals("demo-dubbo-application", dubboApplicationName);
// Case 4 : If "defaultProperties" PropertySource is present in PropertySources
// Rest environment
environment = new MockEnvironment();
propertySources = environment.getPropertySources();
propertySources.addLast(new MapPropertySource("defaultProperties", new HashMap<String, Object>()));
environment.setProperty("spring.application.name", "demo-dubbo-application");
instance.postProcessEnvironment(environment, springApplication);
defaultPropertySource = propertySources.get("defaultProperties");
dubboApplicationName = defaultPropertySource.getProperty("dubbo.application.name");
Assert.assertEquals("demo-dubbo-application", dubboApplicationName);
// Case 5 : Rest dubbo.config.multiple and dubbo.application.qos-enable
environment = new MockEnvironment();
propertySources = environment.getPropertySources();
propertySources.addLast(new MapPropertySource("defaultProperties", new HashMap<String, Object>()));
environment.setProperty("dubbo.config.multiple", "false");
environment.setProperty("dubbo.application.qos-enable", "true");
instance.postProcessEnvironment(environment, springApplication);
Assert.assertEquals("false", environment.getProperty("dubbo.config.multiple"));
Assert.assertEquals("true", environment.getProperty("dubbo.application.qos-enable"));
}
}

View File

@ -0,0 +1,63 @@
/*
* 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.spring.boot.util;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.StandardEnvironment;
import java.util.HashMap;
import java.util.Map;
/**
* {@link EnvironmentUtils} Test
*
* @see EnvironmentUtils
* @since 2.7.0
*/
public class EnvironmentUtilsTest {
@Test
public void testExtraProperties() {
System.setProperty("user.name", "mercyblitz");
StandardEnvironment environment = new StandardEnvironment();
Map<String, Object> map = new HashMap<>();
map.put("user.name", "Mercy");
MapPropertySource propertySource = new MapPropertySource("first", map);
CompositePropertySource compositePropertySource = new CompositePropertySource("comp");
compositePropertySource.addFirstPropertySource(propertySource);
MutablePropertySources propertySources = environment.getPropertySources();
propertySources.addFirst(compositePropertySource);
Map<String, Object> properties = EnvironmentUtils.extractProperties(environment);
Assert.assertEquals("Mercy", properties.get("user.name"));
}
}

View File

@ -0,0 +1,5 @@
dubbo.application.NAME=hello
dubbo.application.owneR=world
dubbo.registry.Address=10.20.153.17
dubbo.protocol.pORt=20881
dubbo.service.invoke.timeout=2000

View File

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-compatible</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dubbo-spring-boot-actuator-compatible</artifactId>
<description>Apache Dubbo Spring Boot Compatible for Spring Boot 1.x Actuator</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<optional>true</optional>
</dependency>
<!-- @ConfigurationProperties annotation processing (metadata for IDEs) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Dubbo autoconfigure -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-autoconfigure-compatible</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-common</artifactId>
<version>${revision}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-config-spring</artifactId>
<version>${revision}</version>
<optional>true</optional>
</dependency>
<!-- Test Dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,55 @@
/*
* 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.spring.boot.actuate.autoconfigure;
import org.apache.dubbo.spring.boot.actuate.endpoint.DubboEndpoint;
import org.apache.dubbo.spring.boot.autoconfigure.DubboAutoConfiguration;
import org.apache.dubbo.spring.boot.autoconfigure.DubboRelaxedBindingAutoConfiguration;
import org.springframework.boot.actuate.condition.ConditionalOnEnabledEndpoint;
import org.springframework.boot.actuate.endpoint.Endpoint;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Dubbo {@link Endpoint} Auto Configuration is compatible with Spring Boot Actuator 1.x
*
* @since 2.7.0
*/
@Configuration
@ConditionalOnClass(name = {
"org.springframework.boot.actuate.endpoint.Endpoint" // Spring Boot 1.x
})
@AutoConfigureAfter(value = {
DubboAutoConfiguration.class,
DubboRelaxedBindingAutoConfiguration.class
})
@EnableConfigurationProperties(DubboEndpoint.class)
public class DubboEndpointAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnEnabledEndpoint(value = "dubbo")
public DubboEndpoint dubboEndpoint() {
return new DubboEndpoint();
}
}

View File

@ -0,0 +1,39 @@
/*
* 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.spring.boot.actuate.autoconfigure;
import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.AbstractDubboMetadata;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* Dubbo Endpoints Metadata Auto-{@link Configuration}
*/
@ConditionalOnClass(name = {
"org.springframework.boot.actuate.health.Health" // If spring-boot-actuator is present
})
@Configuration
@AutoConfigureAfter(name = {
"org.apache.dubbo.spring.boot.autoconfigure.DubboAutoConfiguration",
"org.apache.dubbo.spring.boot.autoconfigure.DubboRelaxedBindingAutoConfiguration"
})
@ComponentScan(basePackageClasses = AbstractDubboMetadata.class)
public class DubboEndpointMetadataAutoConfiguration {
}

View File

@ -0,0 +1,50 @@
/*
* 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.spring.boot.actuate.autoconfigure;
import org.apache.dubbo.spring.boot.actuate.health.DubboHealthIndicator;
import org.apache.dubbo.spring.boot.actuate.health.DubboHealthIndicatorProperties;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Dubbo {@link DubboHealthIndicator} Auto Configuration
*
* @see HealthIndicator
* @since 2.7.0
*/
@Configuration
@ConditionalOnClass(name = {
"org.springframework.boot.actuate.health.Health"
})
@ConditionalOnProperty(name = "management.health.dubbo.enabled", matchIfMissing = true, havingValue = "true")
@EnableConfigurationProperties(DubboHealthIndicatorProperties.class)
public class DubboHealthIndicatorAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public DubboHealthIndicator dubboHealthIndicator() {
return new DubboHealthIndicator();
}
}

View File

@ -0,0 +1,49 @@
/*
* 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.spring.boot.actuate.autoconfigure;
import org.apache.dubbo.spring.boot.actuate.endpoint.DubboEndpoint;
import org.apache.dubbo.spring.boot.actuate.endpoint.mvc.DubboMvcEndpoint;
import org.springframework.boot.actuate.autoconfigure.ManagementContextConfiguration;
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.annotation.Bean;
/**
* Dubbo {@link MvcEndpoint} {@link ManagementContextConfiguration} for Spring Boot 1.x
*
* @since 2.7.0
*/
@ManagementContextConfiguration
@ConditionalOnClass(name = {
"org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter"
})
@ConditionalOnWebApplication
public class DubboMvcEndpointManagementContextConfiguration {
@Bean
@ConditionalOnBean(DubboEndpoint.class)
@ConditionalOnMissingBean
public DubboMvcEndpoint dubboMvcEndpoint(DubboEndpoint dubboEndpoint) {
return new DubboMvcEndpoint(dubboEndpoint);
}
}

View File

@ -0,0 +1,49 @@
/*
* 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.spring.boot.actuate.endpoint;
import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboMetadata;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.AbstractEndpoint;
import org.springframework.boot.actuate.endpoint.Endpoint;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.Map;
/**
* Actuator {@link Endpoint} to expose Dubbo Meta Data
*
* @see Endpoint
* @since 2.7.0
*/
@ConfigurationProperties(prefix = "endpoints.dubbo", ignoreUnknownFields = false)
public class DubboEndpoint extends AbstractEndpoint<Map<String, Object>> {
@Autowired
private DubboMetadata dubboMetadata;
public DubboEndpoint() {
super("dubbo", true, false);
}
@Override
public Map<String, Object> invoke() {
return dubboMetadata.invoke();
}
}

View File

@ -0,0 +1,124 @@
/*
* 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.spring.boot.actuate.endpoint.metadata;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.spring.ServiceBean;
import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URL;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
import static org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor.BEAN_NAME;
import static org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors;
import static org.springframework.util.ClassUtils.isPrimitiveOrWrapper;
/**
* Abstract Dubbo Meatadata
*
* @since 2.7.0
*/
public abstract class AbstractDubboMetadata implements ApplicationContextAware, EnvironmentAware {
protected ApplicationContext applicationContext;
protected ConfigurableEnvironment environment;
private static boolean isSimpleType(Class<?> type) {
return isPrimitiveOrWrapper(type)
|| type == String.class
|| type == BigDecimal.class
|| type == BigInteger.class
|| type == Date.class
|| type == URL.class
|| type == Class.class
;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Override
public void setEnvironment(Environment environment) {
if (environment instanceof ConfigurableEnvironment) {
this.environment = (ConfigurableEnvironment) environment;
}
}
protected Map<String, Object> resolveBeanMetadata(final Object bean) {
final Map<String, Object> beanMetadata = new LinkedHashMap<>();
try {
BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
Method readMethod = propertyDescriptor.getReadMethod();
if (readMethod != null && isSimpleType(propertyDescriptor.getPropertyType())) {
String name = Introspector.decapitalize(propertyDescriptor.getName());
Object value = readMethod.invoke(bean);
if (value != null) {
beanMetadata.put(name, value);
}
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return beanMetadata;
}
protected Map<String, ServiceBean> getServiceBeansMap() {
return beansOfTypeIncludingAncestors(applicationContext, ServiceBean.class);
}
protected ReferenceAnnotationBeanPostProcessor getReferenceAnnotationBeanPostProcessor() {
return applicationContext.getBean(BEAN_NAME, ReferenceAnnotationBeanPostProcessor.class);
}
protected Map<String, ProtocolConfig> getProtocolConfigsBeanMap() {
return beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class);
}
}

View File

@ -0,0 +1,87 @@
/*
* 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.spring.boot.actuate.endpoint.metadata;
import org.apache.dubbo.config.AbstractConfig;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ConsumerConfig;
import org.apache.dubbo.config.MethodConfig;
import org.apache.dubbo.config.ModuleConfig;
import org.apache.dubbo.config.MonitorConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.ProviderConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ServiceConfig;
import org.springframework.stereotype.Component;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
import static org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors;
/**
* Dubbo Configs Metadata
*
* @since 2.7.0
*/
@Component
public class DubboConfigsMetadata extends AbstractDubboMetadata {
public Map<String, Map<String, Map<String, Object>>> configs() {
Map<String, Map<String, Map<String, Object>>> configsMap = new LinkedHashMap<>();
addDubboConfigBeans(ApplicationConfig.class, configsMap);
addDubboConfigBeans(ConsumerConfig.class, configsMap);
addDubboConfigBeans(MethodConfig.class, configsMap);
addDubboConfigBeans(ModuleConfig.class, configsMap);
addDubboConfigBeans(MonitorConfig.class, configsMap);
addDubboConfigBeans(ProtocolConfig.class, configsMap);
addDubboConfigBeans(ProviderConfig.class, configsMap);
addDubboConfigBeans(ReferenceConfig.class, configsMap);
addDubboConfigBeans(RegistryConfig.class, configsMap);
addDubboConfigBeans(ServiceConfig.class, configsMap);
return configsMap;
}
private void addDubboConfigBeans(Class<? extends AbstractConfig> dubboConfigClass,
Map<String, Map<String, Map<String, Object>>> configsMap) {
Map<String, ? extends AbstractConfig> dubboConfigBeans = beansOfTypeIncludingAncestors(applicationContext, dubboConfigClass);
String name = dubboConfigClass.getSimpleName();
Map<String, Map<String, Object>> beansMetadata = new TreeMap<>();
for (Map.Entry<String, ? extends AbstractConfig> entry : dubboConfigBeans.entrySet()) {
String beanName = entry.getKey();
AbstractConfig configBean = entry.getValue();
Map<String, Object> configBeanMeta = resolveBeanMetadata(configBean);
beansMetadata.put(beanName, configBeanMeta);
}
configsMap.put(name, beansMetadata);
}
}

View File

@ -0,0 +1,62 @@
/*
* 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.spring.boot.actuate.endpoint.metadata;
import org.apache.dubbo.common.Version;
import org.apache.dubbo.spring.boot.util.DubboUtils;
import org.springframework.stereotype.Component;
import java.util.LinkedHashMap;
import java.util.Map;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_GITHUB_URL;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_MAILING_LIST;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_SPRING_BOOT_GITHUB_URL;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_SPRING_BOOT_GIT_URL;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_SPRING_BOOT_ISSUES_URL;
/**
* Dubbo Metadata
* @since 2.7.0
*/
@Component
public class DubboMetadata {
public Map<String, Object> invoke() {
Map<String, Object> metaData = new LinkedHashMap<>();
metaData.put("timestamp", System.currentTimeMillis());
Map<String, String> versions = new LinkedHashMap<>();
versions.put("dubbo-spring-boot", Version.getVersion(DubboUtils.class, "1.0.0"));
versions.put("dubbo", Version.getVersion());
Map<String, String> urls = new LinkedHashMap<>();
urls.put("dubbo", DUBBO_GITHUB_URL);
urls.put("mailing-list", DUBBO_MAILING_LIST);
urls.put("github", DUBBO_SPRING_BOOT_GITHUB_URL);
urls.put("issues", DUBBO_SPRING_BOOT_ISSUES_URL);
urls.put("git", DUBBO_SPRING_BOOT_GIT_URL);
metaData.put("versions", versions);
metaData.put("urls", urls);
return metaData;
}
}

View File

@ -0,0 +1,36 @@
/*
* 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.spring.boot.actuate.endpoint.metadata;
import org.springframework.stereotype.Component;
import java.util.SortedMap;
import static org.apache.dubbo.spring.boot.util.DubboUtils.filterDubboProperties;
/**
* Dubbo Properties Metadata
*
* @since 2.7.0
*/
@Component
public class DubboPropertiesMetadata extends AbstractDubboMetadata {
public SortedMap<String, Object> properties() {
return filterDubboProperties(environment);
}
}

View File

@ -0,0 +1,79 @@
/*
* 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.spring.boot.actuate.endpoint.metadata;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.spring.ReferenceBean;
import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor;
import org.springframework.beans.factory.annotation.InjectionMetadata;
import org.springframework.stereotype.Component;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* {@link DubboReference} Metadata
*
* @since 2.7.0
*/
@Component
public class DubboReferencesMetadata extends AbstractDubboMetadata {
public Map<String, Map<String, Object>> references() {
Map<String, Map<String, Object>> referencesMetadata = new LinkedHashMap<>();
ReferenceAnnotationBeanPostProcessor beanPostProcessor = getReferenceAnnotationBeanPostProcessor();
referencesMetadata.putAll(buildReferencesMetadata(beanPostProcessor.getInjectedFieldReferenceBeanMap()));
referencesMetadata.putAll(buildReferencesMetadata(beanPostProcessor.getInjectedMethodReferenceBeanMap()));
return referencesMetadata;
}
private Map<String, Map<String, Object>> buildReferencesMetadata(
Map<InjectionMetadata.InjectedElement, ReferenceBean<?>> injectedElementReferenceBeanMap) {
Map<String, Map<String, Object>> referencesMetadata = new LinkedHashMap<>();
for (Map.Entry<InjectionMetadata.InjectedElement, ReferenceBean<?>> entry :
injectedElementReferenceBeanMap.entrySet()) {
InjectionMetadata.InjectedElement injectedElement = entry.getKey();
ReferenceBean<?> referenceBean = entry.getValue();
ReferenceConfig referenceConfig = referenceBean.getReferenceConfig();
Map<String, Object> beanMetadata = null;
if (referenceConfig != null) {
beanMetadata = resolveBeanMetadata(referenceConfig);
//beanMetadata.put("invoker", resolveBeanMetadata(referenceBean.get()));
} else {
// referenceBean is not initialized
beanMetadata = new LinkedHashMap<>();
}
referencesMetadata.put(String.valueOf(injectedElement.getMember()), beanMetadata);
}
return referencesMetadata;
}
}

View File

@ -0,0 +1,84 @@
/*
* 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.spring.boot.actuate.endpoint.metadata;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.dubbo.config.spring.ServiceBean;
import org.springframework.stereotype.Component;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* {@link DubboService} Metadata
*
* @since 2.7.0
*/
@Component
public class DubboServicesMetadata extends AbstractDubboMetadata {
public Map<String, Map<String, Object>> services() {
Map<String, ServiceBean> serviceBeansMap = getServiceBeansMap();
Map<String, Map<String, Object>> servicesMetadata = new LinkedHashMap<>(serviceBeansMap.size());
for (Map.Entry<String, ServiceBean> entry : serviceBeansMap.entrySet()) {
String serviceBeanName = entry.getKey();
ServiceBean serviceBean = entry.getValue();
Map<String, Object> serviceBeanMetadata = resolveBeanMetadata(serviceBean);
Object service = resolveServiceBean(serviceBeanName, serviceBean);
if (service != null) {
// Add Service implementation class
serviceBeanMetadata.put("serviceClass", service.getClass().getName());
}
servicesMetadata.put(serviceBeanName, serviceBeanMetadata);
}
return servicesMetadata;
}
private Object resolveServiceBean(String serviceBeanName, ServiceBean serviceBean) {
int index = serviceBeanName.indexOf("#");
if (index > -1) {
Class<?> interfaceClass = serviceBean.getInterfaceClass();
String serviceName = serviceBeanName.substring(index + 1);
if (applicationContext.containsBean(serviceName)) {
return applicationContext.getBean(serviceName, interfaceClass);
}
}
return null;
}
}

View File

@ -0,0 +1,78 @@
/*
* 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.spring.boot.actuate.endpoint.metadata;
import org.apache.dubbo.config.ReferenceConfigBase;
import org.apache.dubbo.config.spring.ServiceBean;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.springframework.stereotype.Component;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
import static org.apache.dubbo.registry.support.AbstractRegistryFactory.getRegistries;
/**
* Dubbo Shutdown
*
* @since 2.7.0
*/
@Component
public class DubboShutdownMetadata extends AbstractDubboMetadata {
public Map<String, Object> shutdown() throws Exception {
Map<String, Object> shutdownCountData = new LinkedHashMap<>();
// registries
int registriesCount = getRegistries().size();
// protocols
int protocolsCount = getProtocolConfigsBeanMap().size();
shutdownCountData.put("registries", registriesCount);
shutdownCountData.put("protocols", protocolsCount);
// Service Beans
Map<String, ServiceBean> serviceBeansMap = getServiceBeansMap();
if (!serviceBeansMap.isEmpty()) {
for (ServiceBean serviceBean : serviceBeansMap.values()) {
serviceBean.destroy();
}
}
shutdownCountData.put("services", serviceBeansMap.size());
// Reference Beans
Collection<ReferenceConfigBase<?>> references = ApplicationModel.getConfigManager().getReferences();
for (ReferenceConfigBase<?> reference : references) {
reference.destroy();
}
shutdownCountData.put("references", references.size());
// Set Result to complete
Map<String, Object> shutdownData = new TreeMap<>();
shutdownData.put("shutdown.count", shutdownCountData);
return shutdownData;
}
}

View File

@ -0,0 +1,112 @@
/*
* 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.spring.boot.actuate.endpoint.mvc;
import org.apache.dubbo.spring.boot.actuate.endpoint.DubboEndpoint;
import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboConfigsMetadata;
import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboPropertiesMetadata;
import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboReferencesMetadata;
import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboServicesMetadata;
import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboShutdownMetadata;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter;
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.async.DeferredResult;
import java.util.Map;
import java.util.SortedMap;
/**
* {@link MvcEndpoint} to expose Dubbo Metadata
*
* @see MvcEndpoint
* @since 2.7.0
*/
public class DubboMvcEndpoint extends EndpointMvcAdapter {
public static final String DUBBO_SHUTDOWN_ENDPOINT_URI = "/shutdown";
public static final String DUBBO_CONFIGS_ENDPOINT_URI = "/configs";
public static final String DUBBO_SERVICES_ENDPOINT_URI = "/services";
public static final String DUBBO_REFERENCES_ENDPOINT_URI = "/references";
public static final String DUBBO_PROPERTIES_ENDPOINT_URI = "/properties";
private final Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private DubboShutdownMetadata dubboShutdownMetadata;
@Autowired
private DubboConfigsMetadata dubboConfigsMetadata;
@Autowired
private DubboServicesMetadata dubboServicesMetadata;
@Autowired
private DubboReferencesMetadata dubboReferencesMetadata;
@Autowired
private DubboPropertiesMetadata dubboPropertiesMetadata;
public DubboMvcEndpoint(DubboEndpoint dubboEndpoint) {
super(dubboEndpoint);
}
@RequestMapping(value = DUBBO_SHUTDOWN_ENDPOINT_URI, method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public DeferredResult shutdown() throws Exception {
Map<String, Object> shutdownCountData = dubboShutdownMetadata.shutdown();
return new DeferredResult(null, shutdownCountData);
}
@RequestMapping(value = DUBBO_CONFIGS_ENDPOINT_URI, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public Map<String, Map<String, Map<String, Object>>> configs() {
return dubboConfigsMetadata.configs();
}
@RequestMapping(value = DUBBO_SERVICES_ENDPOINT_URI, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public Map<String, Map<String, Object>> services() {
return dubboServicesMetadata.services();
}
@RequestMapping(value = DUBBO_REFERENCES_ENDPOINT_URI, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public Map<String, Map<String, Object>> references() {
return dubboReferencesMetadata.references();
}
@RequestMapping(value = DUBBO_PROPERTIES_ENDPOINT_URI, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public SortedMap<String, Object> properties() {
return dubboPropertiesMetadata.properties();
}
}

View File

@ -0,0 +1,211 @@
/*
* 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.spring.boot.actuate.health;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.status.StatusChecker;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.ProviderConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.health.AbstractHealthIndicator;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.util.StringUtils;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
/**
* Dubbo {@link HealthIndicator}
*
* @see HealthIndicator
* @since 2.7.0
*/
public class DubboHealthIndicator extends AbstractHealthIndicator {
@Autowired
private DubboHealthIndicatorProperties dubboHealthIndicatorProperties;
@Autowired(required = false)
private Map<String, ProtocolConfig> protocolConfigs = Collections.emptyMap();
@Autowired(required = false)
private Map<String, ProviderConfig> providerConfigs = Collections.emptyMap();
@Override
protected void doHealthCheck(Health.Builder builder) throws Exception {
ExtensionLoader<StatusChecker> extensionLoader = getExtensionLoader(StatusChecker.class);
Map<String, String> statusCheckerNamesMap = resolveStatusCheckerNamesMap();
boolean hasError = false;
boolean hasUnknown = false;
// Up first
builder.up();
for (Map.Entry<String, String> entry : statusCheckerNamesMap.entrySet()) {
String statusCheckerName = entry.getKey();
String source = entry.getValue();
StatusChecker checker = extensionLoader.getExtension(statusCheckerName);
org.apache.dubbo.common.status.Status status = checker.check();
org.apache.dubbo.common.status.Status.Level level = status.getLevel();
if (!hasError && level.equals(org.apache.dubbo.common.status.Status.Level.ERROR)) {
hasError = true;
builder.down();
}
if (!hasError && !hasUnknown && level.equals(org.apache.dubbo.common.status.Status.Level.UNKNOWN)) {
hasUnknown = true;
builder.unknown();
}
Map<String, Object> detail = new LinkedHashMap<>();
detail.put("source", source);
detail.put("status", status);
builder.withDetail(statusCheckerName, detail);
}
}
/**
* Resolves the map of {@link StatusChecker}'s name and its' source.
*
* @return non-null {@link Map}
*/
protected Map<String, String> resolveStatusCheckerNamesMap() {
Map<String, String> statusCheckerNamesMap = new LinkedHashMap<>();
statusCheckerNamesMap.putAll(resolveStatusCheckerNamesMapFromDubboHealthIndicatorProperties());
statusCheckerNamesMap.putAll(resolveStatusCheckerNamesMapFromProtocolConfigs());
statusCheckerNamesMap.putAll(resolveStatusCheckerNamesMapFromProviderConfig());
return statusCheckerNamesMap;
}
private Map<String, String> resolveStatusCheckerNamesMapFromDubboHealthIndicatorProperties() {
DubboHealthIndicatorProperties.Status status =
dubboHealthIndicatorProperties.getStatus();
Map<String, String> statusCheckerNamesMap = new LinkedHashMap<>();
for (String statusName : status.getDefaults()) {
statusCheckerNamesMap.put(statusName, DubboHealthIndicatorProperties.PREFIX + ".status.defaults");
}
for (String statusName : status.getExtras()) {
statusCheckerNamesMap.put(statusName, DubboHealthIndicatorProperties.PREFIX + ".status.extras");
}
return statusCheckerNamesMap;
}
private Map<String, String> resolveStatusCheckerNamesMapFromProtocolConfigs() {
Map<String, String> statusCheckerNamesMap = new LinkedHashMap<>();
for (Map.Entry<String, ProtocolConfig> entry : protocolConfigs.entrySet()) {
String beanName = entry.getKey();
ProtocolConfig protocolConfig = entry.getValue();
Set<String> statusCheckerNames = getStatusCheckerNames(protocolConfig);
for (String statusCheckerName : statusCheckerNames) {
String source = buildSource(beanName, protocolConfig);
statusCheckerNamesMap.put(statusCheckerName, source);
}
}
return statusCheckerNamesMap;
}
private Map<String, String> resolveStatusCheckerNamesMapFromProviderConfig() {
Map<String, String> statusCheckerNamesMap = new LinkedHashMap<>();
for (Map.Entry<String, ProviderConfig> entry : providerConfigs.entrySet()) {
String beanName = entry.getKey();
ProviderConfig providerConfig = entry.getValue();
Set<String> statusCheckerNames = getStatusCheckerNames(providerConfig);
for (String statusCheckerName : statusCheckerNames) {
String source = buildSource(beanName, providerConfig);
statusCheckerNamesMap.put(statusCheckerName, source);
}
}
return statusCheckerNamesMap;
}
private Set<String> getStatusCheckerNames(ProtocolConfig protocolConfig) {
String status = protocolConfig.getStatus();
return StringUtils.commaDelimitedListToSet(status);
}
private Set<String> getStatusCheckerNames(ProviderConfig providerConfig) {
String status = providerConfig.getStatus();
return StringUtils.commaDelimitedListToSet(status);
}
private String buildSource(String beanName, Object bean) {
return beanName + "@" + bean.getClass().getSimpleName() + ".getStatus()";
}
}

View File

@ -0,0 +1,99 @@
/*
* 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.spring.boot.actuate.health;
import org.apache.dubbo.common.status.StatusChecker;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;
import static org.apache.dubbo.spring.boot.actuate.health.DubboHealthIndicatorProperties.PREFIX;
/**
* Dubbo {@link HealthIndicator} Properties
*
* @see HealthIndicator
* @since 2.7.0
*/
@ConfigurationProperties(prefix = PREFIX, ignoreUnknownFields = false)
public class DubboHealthIndicatorProperties {
/**
* The prefix of {@link DubboHealthIndicatorProperties}
*/
public static final String PREFIX = "management.health.dubbo";
private Status status = new Status();
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
/**
* The nested class for {@link StatusChecker}'s names
* <pre>
* registry= org.apache.dubbo.registry.status.RegistryStatusChecker
* spring= org.apache.dubbo.config.spring.status.SpringStatusChecker
* datasource= org.apache.dubbo.config.spring.status.DataSourceStatusChecker
* memory= org.apache.dubbo.common.status.support.MemoryStatusChecker
* load= org.apache.dubbo.common.status.support.LoadStatusChecker
* server= org.apache.dubbo.rpc.protocol.dubbo.status.ServerStatusChecker
* threadpool= org.apache.dubbo.rpc.protocol.dubbo.status.ThreadPoolStatusChecker
* </pre>
*
* @see StatusChecker
*/
public static class Status {
/**
* The defaults names of {@link StatusChecker}
* <p>
* The defaults : "memory", "load"
*/
private Set<String> defaults = new LinkedHashSet<>(Arrays.asList("memory", "load"));
/**
* The extra names of {@link StatusChecker}
*/
private Set<String> extras = new LinkedHashSet<>();
public Set<String> getDefaults() {
return defaults;
}
public void setDefaults(Set<String> defaults) {
this.defaults = defaults;
}
public Set<String> getExtras() {
return extras;
}
public void setExtras(Set<String> extras) {
this.extras = extras;
}
}
}

View File

@ -0,0 +1,6 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.apache.dubbo.spring.boot.actuate.autoconfigure.DubboEndpointAutoConfiguration,\
org.apache.dubbo.spring.boot.actuate.autoconfigure.DubboHealthIndicatorAutoConfiguration,\
org.apache.dubbo.spring.boot.actuate.autoconfigure.DubboEndpointMetadataAutoConfiguration
org.springframework.boot.actuate.autoconfigure.ManagementContextConfiguration=\
org.apache.dubbo.spring.boot.actuate.autoconfigure.DubboMvcEndpointManagementContextConfiguration

View File

@ -0,0 +1,238 @@
/*
* 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.spring.boot.actuate.autoconfigure;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.dubbo.spring.boot.actuate.endpoint.DubboEndpoint;
import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboConfigsMetadata;
import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboPropertiesMetadata;
import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboReferencesMetadata;
import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboServicesMetadata;
import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboShutdownMetadata;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.client.RestTemplate;
import java.util.Map;
import java.util.SortedMap;
import java.util.function.Supplier;
/**
* {@link DubboEndpointAutoConfiguration} Test
*
* @since 2.7.0
*/
@RunWith(SpringRunner.class)
@SpringBootTest(
classes = {
DubboEndpointAutoConfiguration.class,
DubboEndpointAutoConfigurationTest.class
},
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
properties = {
"dubbo.service.version = 1.0.0",
"dubbo.application.id = my-application",
"dubbo.application.name = dubbo-demo-application",
"dubbo.module.id = my-module",
"dubbo.module.name = dubbo-demo-module",
"dubbo.registry.id = my-registry",
"dubbo.registry.address = N/A",
"dubbo.protocol.id=my-protocol",
"dubbo.protocol.name=dubbo",
"dubbo.protocol.port=20880",
"dubbo.provider.id=my-provider",
"dubbo.provider.host=127.0.0.1",
"dubbo.scan.basePackages=org.apache.dubbo.spring.boot.actuate.autoconfigure",
"endpoints.enabled = true",
"management.security.enabled = false",
"management.contextPath = /actuator",
"endpoints.dubbo.enabled = true",
"endpoints.dubbo.sensitive = false",
"endpoints.dubboshutdown.enabled = true",
"endpoints.dubboconfigs.enabled = true",
"endpoints.dubboservices.enabled = true",
"endpoints.dubboreferences.enabled = true",
"endpoints.dubboproperties.enabled = true",
})
@EnableAutoConfiguration
@Ignore
public class DubboEndpointAutoConfigurationTest {
@Autowired
private DubboEndpoint dubboEndpoint;
@Autowired
private DubboConfigsMetadata dubboConfigsMetadata;
@Autowired
private DubboPropertiesMetadata dubboProperties;
@Autowired
private DubboReferencesMetadata dubboReferencesMetadata;
@Autowired
private DubboServicesMetadata dubboServicesMetadata;
@Autowired
private DubboShutdownMetadata dubboShutdownMetadata;
private RestTemplate restTemplate = new RestTemplate();
@Autowired
private ObjectMapper objectMapper;
@Value("http://127.0.0.1:${local.management.port}${management.contextPath:}")
private String actuatorBaseURL;
@Test
public void testShutdown() throws Exception {
Map<String, Object> value = dubboShutdownMetadata.shutdown();
Map<String, Object> shutdownCounts = (Map<String, Object>) value.get("shutdown.count");
Assert.assertEquals(0, shutdownCounts.get("registries"));
Assert.assertEquals(1, shutdownCounts.get("protocols"));
Assert.assertEquals(1, shutdownCounts.get("services"));
Assert.assertEquals(0, shutdownCounts.get("references"));
}
@Test
public void testConfigs() {
Map<String, Map<String, Map<String, Object>>> configsMap = dubboConfigsMetadata.configs();
Map<String, Map<String, Object>> beansMetadata = configsMap.get("ApplicationConfig");
Assert.assertEquals("dubbo-demo-application", beansMetadata.get("my-application").get("name"));
beansMetadata = configsMap.get("ConsumerConfig");
Assert.assertTrue(beansMetadata.isEmpty());
beansMetadata = configsMap.get("MethodConfig");
Assert.assertTrue(beansMetadata.isEmpty());
beansMetadata = configsMap.get("ModuleConfig");
Assert.assertEquals("dubbo-demo-module", beansMetadata.get("my-module").get("name"));
beansMetadata = configsMap.get("MonitorConfig");
Assert.assertTrue(beansMetadata.isEmpty());
beansMetadata = configsMap.get("ProtocolConfig");
Assert.assertEquals("dubbo", beansMetadata.get("my-protocol").get("name"));
beansMetadata = configsMap.get("ProviderConfig");
Assert.assertEquals("127.0.0.1", beansMetadata.get("my-provider").get("host"));
beansMetadata = configsMap.get("ReferenceConfig");
Assert.assertTrue(beansMetadata.isEmpty());
beansMetadata = configsMap.get("RegistryConfig");
Assert.assertEquals("N/A", beansMetadata.get("my-registry").get("address"));
beansMetadata = configsMap.get("ServiceConfig");
Assert.assertFalse(beansMetadata.isEmpty());
}
@Test
public void testServices() {
Map<String, Map<String, Object>> services = dubboServicesMetadata.services();
Assert.assertEquals(1, services.size());
Map<String, Object> demoServiceMeta = services.get("ServiceBean:org.apache.dubbo.spring.boot.actuate.autoconfigure.DubboEndpointAutoConfigurationTest$DemoService:1.0.0");
Assert.assertEquals("1.0.0", demoServiceMeta.get("version"));
}
@Test
public void testReferences() {
Map<String, Map<String, Object>> references = dubboReferencesMetadata.references();
Assert.assertTrue(references.isEmpty());
}
@Test
public void testProperties() {
SortedMap<String, Object> properties = dubboProperties.properties();
Assert.assertEquals("my-application", properties.get("dubbo.application.id"));
Assert.assertEquals("dubbo-demo-application", properties.get("dubbo.application.name"));
Assert.assertEquals("my-module", properties.get("dubbo.module.id"));
Assert.assertEquals("dubbo-demo-module", properties.get("dubbo.module.name"));
Assert.assertEquals("my-registry", properties.get("dubbo.registry.id"));
Assert.assertEquals("N/A", properties.get("dubbo.registry.address"));
Assert.assertEquals("my-protocol", properties.get("dubbo.protocol.id"));
Assert.assertEquals("dubbo", properties.get("dubbo.protocol.name"));
Assert.assertEquals("20880", properties.get("dubbo.protocol.port"));
Assert.assertEquals("my-provider", properties.get("dubbo.provider.id"));
Assert.assertEquals("127.0.0.1", properties.get("dubbo.provider.host"));
Assert.assertEquals("org.apache.dubbo.spring.boot.actuate.autoconfigure", properties.get("dubbo.scan.basePackages"));
}
@Test
public void testHttpEndpoints() throws JsonProcessingException {
// testHttpEndpoint("/dubbo", dubboEndpoint::invoke);
testHttpEndpoint("/dubbo/configs", dubboConfigsMetadata::configs);
testHttpEndpoint("/dubbo/services", dubboServicesMetadata::services);
testHttpEndpoint("/dubbo/references", dubboReferencesMetadata::references);
testHttpEndpoint("/dubbo/properties", dubboProperties::properties);
}
private void testHttpEndpoint(String actuatorURI, Supplier<Map> resultsSupplier) throws JsonProcessingException {
String actuatorURL = actuatorBaseURL + actuatorURI;
String response = restTemplate.getForObject(actuatorURL, String.class);
Assert.assertEquals(objectMapper.writeValueAsString(resultsSupplier.get()), response);
}
interface DemoService {
String sayHello(String name);
}
@DubboService(
version = "${dubbo.service.version}",
application = "${dubbo.application.id}",
protocol = "${dubbo.protocol.id}",
registry = "${dubbo.registry.id}"
)
static class DefaultDemoService implements DemoService {
public String sayHello(String name) {
return "Hello, " + name + " (from Spring Boot)";
}
}
}

View File

@ -0,0 +1,89 @@
/*
* 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.spring.boot.actuate.health;
import org.apache.dubbo.config.spring.context.annotation.EnableDubboConfig;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.Status;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Map;
/**
* {@link DubboHealthIndicator} Test
*
* @see DubboHealthIndicator
* @since 2.7.0
*/
@RunWith(SpringRunner.class)
@TestPropertySource(properties = {
"dubbo.application.id = my-application-1",
"dubbo.application.name = dubbo-demo-application-1",
"dubbo.protocol.id = dubbo-protocol",
"dubbo.protocol.name = dubbo",
"dubbo.protocol.port = 12345",
"dubbo.protocol.status = registry",
"dubbo.provider.id = dubbo-provider",
"dubbo.provider.status = server",
"management.health.dubbo.status.defaults = memory",
"management.health.dubbo.status.extras = load,threadpool"
})
@SpringBootTest(
classes = {
DubboHealthIndicator.class,
DubboHealthIndicatorTest.class
}
)
@EnableConfigurationProperties(DubboHealthIndicatorProperties.class)
@EnableDubboConfig
public class DubboHealthIndicatorTest {
@Autowired
private DubboHealthIndicator dubboHealthIndicator;
@Test
public void testResolveStatusCheckerNamesMap() {
Map<String, String> statusCheckerNamesMap = dubboHealthIndicator.resolveStatusCheckerNamesMap();
Assert.assertEquals(5, statusCheckerNamesMap.size());
Assert.assertEquals("dubbo-protocol@ProtocolConfig.getStatus()", statusCheckerNamesMap.get("registry"));
Assert.assertEquals("dubbo-provider@ProviderConfig.getStatus()", statusCheckerNamesMap.get("server"));
Assert.assertEquals("management.health.dubbo.status.defaults", statusCheckerNamesMap.get("memory"));
Assert.assertEquals("management.health.dubbo.status.extras", statusCheckerNamesMap.get("load"));
Assert.assertEquals("management.health.dubbo.status.extras", statusCheckerNamesMap.get("threadpool"));
}
@Test
public void testHealth() {
Health health = dubboHealthIndicator.health();
Assert.assertEquals(Status.UNKNOWN, health.getStatus());
}
}

View File

@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-compatible</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dubbo-spring-boot-autoconfigure-compatible</artifactId>
<description>Apache Dubbo Spring Boot Compatible for Spring Boot 1.x Auto-Configure</description>
<dependencies>
<!-- Spring Boot dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
<optional>true</optional>
</dependency>
<!-- @ConfigurationProperties annotation processing (metadata for IDEs) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-common</artifactId>
<version>${revision}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-config-spring</artifactId>
<version>${revision}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>${revision}</version>
</dependency>
<!-- Test Dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,112 @@
/*
* 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.spring.boot.autoconfigure;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor;
import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceClassPostProcessor;
import org.apache.dubbo.config.spring.context.DubboBootstrapApplicationListener;
import org.apache.dubbo.config.spring.context.DubboLifecycleComponentApplicationListener;
import org.apache.dubbo.config.spring.context.annotation.EnableDubboConfig;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Set;
import static org.apache.dubbo.spring.boot.util.DubboUtils.BASE_PACKAGES_BEAN_NAME;
import static org.apache.dubbo.spring.boot.util.DubboUtils.BASE_PACKAGES_PROPERTY_NAME;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_PREFIX;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_SCAN_PREFIX;
/**
* Dubbo Auto {@link Configuration}
*
* @see DubboReference
* @see DubboService
* @see ServiceClassPostProcessor
* @see ReferenceAnnotationBeanPostProcessor
* @since 2.7.0
*/
@ConditionalOnProperty(prefix = DUBBO_PREFIX, name = "enabled", matchIfMissing = true)
@Configuration
@AutoConfigureAfter(DubboRelaxedBindingAutoConfiguration.class)
@EnableConfigurationProperties(DubboConfigurationProperties.class)
@EnableDubboConfig
public class DubboAutoConfiguration implements ApplicationContextAware, BeanDefinitionRegistryPostProcessor {
/**
* Creates {@link ServiceClassPostProcessor} Bean
*
* @param packagesToScan the packages to scan
* @return {@link ServiceClassPostProcessor}
*/
@ConditionalOnProperty(prefix = DUBBO_SCAN_PREFIX, name = BASE_PACKAGES_PROPERTY_NAME)
@ConditionalOnBean(name = BASE_PACKAGES_BEAN_NAME)
@Bean
public ServiceClassPostProcessor serviceClassPostProcessor(@Qualifier(BASE_PACKAGES_BEAN_NAME)
Set<String> packagesToScan) {
return new ServiceClassPostProcessor(packagesToScan);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (applicationContext instanceof ConfigurableApplicationContext) {
ConfigurableApplicationContext context = (ConfigurableApplicationContext) applicationContext;
DubboLifecycleComponentApplicationListener dubboLifecycleComponentApplicationListener
= new DubboLifecycleComponentApplicationListener();
dubboLifecycleComponentApplicationListener.setApplicationContext(applicationContext);
context.addApplicationListener(dubboLifecycleComponentApplicationListener);
DubboBootstrapApplicationListener dubboBootstrapApplicationListener = new DubboBootstrapApplicationListener();
dubboBootstrapApplicationListener.setApplicationContext(applicationContext);
context.addApplicationListener(dubboBootstrapApplicationListener);
}
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
// Remove the BeanDefinitions of ApplicationListener from DubboBeanUtils#registerCommonBeans(BeanDefinitionRegistry)
// TODO Refactoring in Dubbo 2.7.9
removeBeanDefinition(registry, DubboLifecycleComponentApplicationListener.BEAN_NAME);
removeBeanDefinition(registry, DubboBootstrapApplicationListener.BEAN_NAME);
}
private void removeBeanDefinition(BeanDefinitionRegistry registry, String beanName) {
if (registry.containsBeanDefinition(beanName)) {
registry.removeBeanDefinition(beanName);
}
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// DO NOTHING
}
}

View File

@ -0,0 +1,300 @@
/*
* 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.spring.boot.autoconfigure;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ConsumerConfig;
import org.apache.dubbo.config.MetadataReportConfig;
import org.apache.dubbo.config.ModuleConfig;
import org.apache.dubbo.config.MonitorConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.ProviderConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.spring.ConfigCenterBean;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DEFAULT_MULTIPLE_CONFIG_PROPERTY_VALUE;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DEFAULT_OVERRIDE_CONFIG_PROPERTY_VALUE;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_PREFIX;
/**
* Dubbo {@link ConfigurationProperties Config Properties} only used to generate JSON metadata(non-public class)
*
* @since 2.7.1
*/
@ConfigurationProperties(DUBBO_PREFIX)
public class DubboConfigurationProperties {
@NestedConfigurationProperty
private Config config = new Config();
@NestedConfigurationProperty
private Scan scan = new Scan();
// Single Config Bindings
@NestedConfigurationProperty
private ApplicationConfig application = new ApplicationConfig();
@NestedConfigurationProperty
private ModuleConfig module = new ModuleConfig();
@NestedConfigurationProperty
private RegistryConfig registry = new RegistryConfig();
@NestedConfigurationProperty
private ProtocolConfig protocol = new ProtocolConfig();
@NestedConfigurationProperty
private MonitorConfig monitor = new MonitorConfig();
@NestedConfigurationProperty
private ProviderConfig provider = new ProviderConfig();
@NestedConfigurationProperty
private ConsumerConfig consumer = new ConsumerConfig();
@NestedConfigurationProperty
private ConfigCenterBean configCenter = new ConfigCenterBean();
@NestedConfigurationProperty
private MetadataReportConfig metadataReport = new MetadataReportConfig();
// Multiple Config Bindings
private Map<String, ModuleConfig> modules = new LinkedHashMap<>();
private Map<String, RegistryConfig> registries = new LinkedHashMap<>();
private Map<String, ProtocolConfig> protocols = new LinkedHashMap<>();
private Map<String, MonitorConfig> monitors = new LinkedHashMap<>();
private Map<String, ProviderConfig> providers = new LinkedHashMap<>();
private Map<String, ConsumerConfig> consumers = new LinkedHashMap<>();
private Map<String, ConfigCenterBean> configCenters = new LinkedHashMap<>();
private Map<String, MetadataReportConfig> metadataReports = new LinkedHashMap<>();
public Config getConfig() {
return config;
}
public void setConfig(Config config) {
this.config = config;
}
public Scan getScan() {
return scan;
}
public void setScan(Scan scan) {
this.scan = scan;
}
public ApplicationConfig getApplication() {
return application;
}
public void setApplication(ApplicationConfig application) {
this.application = application;
}
public ModuleConfig getModule() {
return module;
}
public void setModule(ModuleConfig module) {
this.module = module;
}
public RegistryConfig getRegistry() {
return registry;
}
public void setRegistry(RegistryConfig registry) {
this.registry = registry;
}
public ProtocolConfig getProtocol() {
return protocol;
}
public void setProtocol(ProtocolConfig protocol) {
this.protocol = protocol;
}
public MonitorConfig getMonitor() {
return monitor;
}
public void setMonitor(MonitorConfig monitor) {
this.monitor = monitor;
}
public ProviderConfig getProvider() {
return provider;
}
public void setProvider(ProviderConfig provider) {
this.provider = provider;
}
public ConsumerConfig getConsumer() {
return consumer;
}
public void setConsumer(ConsumerConfig consumer) {
this.consumer = consumer;
}
public ConfigCenterBean getConfigCenter() {
return configCenter;
}
public void setConfigCenter(ConfigCenterBean configCenter) {
this.configCenter = configCenter;
}
public MetadataReportConfig getMetadataReport() {
return metadataReport;
}
public void setMetadataReport(MetadataReportConfig metadataReport) {
this.metadataReport = metadataReport;
}
public Map<String, ModuleConfig> getModules() {
return modules;
}
public void setModules(Map<String, ModuleConfig> modules) {
this.modules = modules;
}
public Map<String, RegistryConfig> getRegistries() {
return registries;
}
public void setRegistries(Map<String, RegistryConfig> registries) {
this.registries = registries;
}
public Map<String, ProtocolConfig> getProtocols() {
return protocols;
}
public void setProtocols(Map<String, ProtocolConfig> protocols) {
this.protocols = protocols;
}
public Map<String, MonitorConfig> getMonitors() {
return monitors;
}
public void setMonitors(Map<String, MonitorConfig> monitors) {
this.monitors = monitors;
}
public Map<String, ProviderConfig> getProviders() {
return providers;
}
public void setProviders(Map<String, ProviderConfig> providers) {
this.providers = providers;
}
public Map<String, ConsumerConfig> getConsumers() {
return consumers;
}
public void setConsumers(Map<String, ConsumerConfig> consumers) {
this.consumers = consumers;
}
public Map<String, ConfigCenterBean> getConfigCenters() {
return configCenters;
}
public void setConfigCenters(Map<String, ConfigCenterBean> configCenters) {
this.configCenters = configCenters;
}
public Map<String, MetadataReportConfig> getMetadataReports() {
return metadataReports;
}
public void setMetadataReports(Map<String, MetadataReportConfig> metadataReports) {
this.metadataReports = metadataReports;
}
static class Config {
/**
* Indicates multiple properties binding from externalized configuration or not.
*/
private boolean multiple = DEFAULT_MULTIPLE_CONFIG_PROPERTY_VALUE;
/**
* The property name of override Dubbo config
*/
private boolean override = DEFAULT_OVERRIDE_CONFIG_PROPERTY_VALUE;
public boolean isOverride() {
return override;
}
public void setOverride(boolean override) {
this.override = override;
}
public boolean isMultiple() {
return multiple;
}
public void setMultiple(boolean multiple) {
this.multiple = multiple;
}
}
static class Scan {
/**
* The basePackages to scan , the multiple-value is delimited by comma
*
* @see EnableDubbo#scanBasePackages()
*/
private Set<String> basePackages = new LinkedHashSet<>();
public Set<String> getBasePackages() {
return basePackages;
}
public void setBasePackages(Set<String> basePackages) {
this.basePackages = basePackages;
}
}
}

View File

@ -0,0 +1,73 @@
/*
* 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.spring.boot.autoconfigure;
import com.alibaba.spring.context.config.ConfigurationBeanBinder;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertyResolver;
import java.util.Set;
import static java.util.Collections.emptySet;
import static org.apache.dubbo.spring.boot.util.DubboUtils.BASE_PACKAGES_BEAN_NAME;
import static org.apache.dubbo.spring.boot.util.DubboUtils.BASE_PACKAGES_PROPERTY_NAME;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_PREFIX;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_SCAN_PREFIX;
import static org.apache.dubbo.spring.boot.util.DubboUtils.RELAXED_DUBBO_CONFIG_BINDER_BEAN_NAME;
import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE;
/**
* Dubbo Relaxed Binding Auto-{@link Configuration} for Spring Boot 1.x
*/
@ConditionalOnProperty(prefix = DUBBO_PREFIX, name = "enabled", matchIfMissing = true)
@ConditionalOnClass(name = "org.springframework.boot.bind.RelaxedPropertyResolver")
@Configuration
public class DubboRelaxedBindingAutoConfiguration {
public PropertyResolver dubboScanBasePackagesPropertyResolver(Environment environment) {
return new RelaxedPropertyResolver(environment, DUBBO_SCAN_PREFIX);
}
/**
* The bean is used to scan the packages of Dubbo Service classes
*
* @param environment {@link Environment} instance
* @return non-null {@link Set}
* @since 2.7.8
*/
@ConditionalOnMissingBean(name = BASE_PACKAGES_BEAN_NAME)
@Bean(name = BASE_PACKAGES_BEAN_NAME)
public Set<String> dubboBasePackages(Environment environment) {
PropertyResolver propertyResolver = dubboScanBasePackagesPropertyResolver(environment);
return propertyResolver.getProperty(BASE_PACKAGES_PROPERTY_NAME, Set.class, emptySet());
}
@ConditionalOnMissingBean(name = RELAXED_DUBBO_CONFIG_BINDER_BEAN_NAME, value = ConfigurationBeanBinder.class)
@Bean(RELAXED_DUBBO_CONFIG_BINDER_BEAN_NAME)
@Scope(scopeName = SCOPE_PROTOTYPE)
public ConfigurationBeanBinder relaxedDubboConfigBinder() {
return new RelaxedDubboConfigBinder();
}
}

View File

@ -0,0 +1,48 @@
/*
* 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.spring.boot.autoconfigure;
import org.apache.dubbo.config.spring.context.properties.DubboConfigBinder;
import com.alibaba.spring.context.config.ConfigurationBeanBinder;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.boot.bind.RelaxedDataBinder;
import java.util.Map;
/**
* Spring Boot Relaxed {@link DubboConfigBinder} implementation
*
* @since 2.7.0
*/
class RelaxedDubboConfigBinder implements ConfigurationBeanBinder {
@Override
public void bind(Map<String, Object> configurationProperties, boolean ignoreUnknownFields,
boolean ignoreInvalidFields, Object configurationBean) {
RelaxedDataBinder relaxedDataBinder = new RelaxedDataBinder(configurationBean);
// Set ignored*
relaxedDataBinder.setIgnoreInvalidFields(ignoreInvalidFields);
relaxedDataBinder.setIgnoreUnknownFields(ignoreUnknownFields);
// Get properties under specified prefix from PropertySources
// Convert Map to MutablePropertyValues
MutablePropertyValues propertyValues = new MutablePropertyValues(configurationProperties);
// Bind
relaxedDataBinder.bind(propertyValues);
}
}

View File

@ -0,0 +1,115 @@
/*
* 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.spring.boot.beans.factory.config;
import org.apache.dubbo.config.ServiceConfig;
import org.apache.dubbo.config.spring.ServiceBean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.CommonAnnotationBeanPostProcessor;
import org.springframework.core.Ordered;
import org.springframework.core.PriorityOrdered;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import static org.springframework.util.ClassUtils.getUserClass;
import static org.springframework.util.ClassUtils.isAssignable;
/**
* The post-processor for resolving the id conflict of {@link ServiceBean} when an interface is
* implemented by multiple services with different groups or versions that are exported on one provider
* <p>
* Current implementation is a temporary resolution, and will be removed in the future.
*
* @see CommonAnnotationBeanPostProcessor
* @since 2.7.7
* @deprecated
*/
public class ServiceBeanIdConflictProcessor implements MergedBeanDefinitionPostProcessor, DisposableBean, PriorityOrdered {
/**
* The key is the class names of interfaces that were exported by {@link ServiceBean}
* The value is bean names of {@link ServiceBean} or {@link ServiceConfig}.
*/
private Map<String, String> interfaceNamesToBeanNames = new HashMap<>();
/**
* Holds the bean names of {@link ServiceBean} or {@link ServiceConfig}.
*/
private Set<String> conflictedBeanNames = new LinkedHashSet<>();
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
// Get raw bean type
Class<?> rawBeanType = getUserClass(beanType);
if (isAssignable(ServiceConfig.class, rawBeanType)) { // ServiceConfig type or sub-type
String interfaceName = (String) beanDefinition.getPropertyValues().get("interface");
String mappedBeanName = interfaceNamesToBeanNames.putIfAbsent(interfaceName, beanName);
// If mapped bean name exists and does not equal current bean name
if (mappedBeanName != null && !mappedBeanName.equals(beanName)) {
// conflictedBeanNames will record current bean name.
conflictedBeanNames.add(beanName);
}
}
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (conflictedBeanNames.contains(beanName) && bean instanceof ServiceConfig) {
ServiceConfig serviceConfig = (ServiceConfig) bean;
if (isConflictedServiceConfig(serviceConfig)) {
// Set id as the bean name
serviceConfig.setId(beanName);
}
}
return bean;
}
private boolean isConflictedServiceConfig(ServiceConfig serviceConfig) {
return Objects.equals(serviceConfig.getId(), serviceConfig.getInterface());
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
/**
* Keep the order being higher than {@link CommonAnnotationBeanPostProcessor#getOrder()} that is
* {@link Ordered#LOWEST_PRECEDENCE}
*
* @return {@link Ordered#LOWEST_PRECEDENCE} +1
*/
@Override
public int getOrder() {
return LOWEST_PRECEDENCE + 1;
}
@Override
public void destroy() throws Exception {
interfaceNamesToBeanNames.clear();
conflictedBeanNames.clear();
}
}

View File

@ -0,0 +1,50 @@
/*
* 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.spring.boot.context;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.Ordered;
/**
* Dubbo {@link ApplicationContextInitializer} implementation
*
* @see ApplicationContextInitializer
* @since 2.7.1
*/
public class DubboApplicationContextInitializer implements ApplicationContextInitializer, Ordered {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
overrideBeanDefinitions(applicationContext);
}
private void overrideBeanDefinitions(ConfigurableApplicationContext applicationContext) {
// @since 2.7.8 OverrideBeanDefinitionRegistryPostProcessor has been removed
// applicationContext.addBeanFactoryPostProcessor(new OverrideBeanDefinitionRegistryPostProcessor());
// @since 2.7.5 DubboConfigBeanDefinitionConflictProcessor has been removed
// @see {@link DubboConfigBeanDefinitionConflictApplicationListener}
// applicationContext.addBeanFactoryPostProcessor(new DubboConfigBeanDefinitionConflictProcessor());
// TODO Add some components in the future ( after 2.7.8 )
}
@Override
public int getOrder() {
return HIGHEST_PRECEDENCE;
}
}

View File

@ -0,0 +1,199 @@
/*
* 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.spring.boot.context.event;
import org.apache.dubbo.common.lang.ShutdownHookCallbacks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.context.event.SmartApplicationListener;
import org.springframework.util.ClassUtils;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import static java.util.concurrent.Executors.newSingleThreadExecutor;
import static org.springframework.util.ObjectUtils.containsElement;
/**
* Awaiting Non-Web Spring Boot {@link ApplicationListener}
*
* @since 2.7.0
*/
public class AwaitingNonWebApplicationListener implements SmartApplicationListener {
private static final String[] WEB_APPLICATION_CONTEXT_CLASSES = new String[]{
"org.springframework.web.context.WebApplicationContext",
"org.springframework.boot.web.reactive.context.ReactiveWebApplicationContext"
};
private static final Logger logger = LoggerFactory.getLogger(AwaitingNonWebApplicationListener.class);
private static final Class<? extends ApplicationEvent>[] SUPPORTED_APPLICATION_EVENTS =
of(ApplicationReadyEvent.class, ContextClosedEvent.class);
private static final AtomicBoolean awaited = new AtomicBoolean(false);
private static final Integer UNDEFINED_ID = Integer.valueOf(-1);
/**
* Target the application id
*/
private static final AtomicInteger applicationContextId = new AtomicInteger(UNDEFINED_ID);
private static final Lock lock = new ReentrantLock();
private static final Condition condition = lock.newCondition();
private static final ExecutorService executorService = newSingleThreadExecutor();
private static <T> T[] of(T... values) {
return values;
}
static AtomicBoolean getAwaited() {
return awaited;
}
@Override
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
return containsElement(SUPPORTED_APPLICATION_EVENTS, eventType);
}
@Override
public boolean supportsSourceType(Class<?> sourceType) {
return true;
}
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationReadyEvent) {
onApplicationReadyEvent((ApplicationReadyEvent) event);
}
}
@Override
public int getOrder() {
return LOWEST_PRECEDENCE;
}
protected void onApplicationReadyEvent(ApplicationReadyEvent event) {
final ConfigurableApplicationContext applicationContext = event.getApplicationContext();
if (!isRootApplicationContext(applicationContext) || isWebApplication(applicationContext)) {
return;
}
if (applicationContextId.compareAndSet(UNDEFINED_ID, applicationContext.hashCode())) {
await();
releaseOnExit();
}
}
/**
* @since 2.7.8
*/
private void releaseOnExit() {
ShutdownHookCallbacks.INSTANCE.addCallback(this::release);
}
private boolean isRootApplicationContext(ApplicationContext applicationContext) {
return applicationContext.getParent() == null;
}
private boolean isWebApplication(ApplicationContext applicationContext) {
boolean webApplication = false;
for (String contextClass : WEB_APPLICATION_CONTEXT_CLASSES) {
if (isAssignable(contextClass, applicationContext.getClass(), applicationContext.getClassLoader())) {
webApplication = true;
break;
}
}
return webApplication;
}
private static boolean isAssignable(String target, Class<?> type, ClassLoader classLoader) {
try {
return ClassUtils.resolveClassName(target, classLoader).isAssignableFrom(type);
} catch (Throwable ex) {
return false;
}
}
protected void await() {
// has been waited, return immediately
if (awaited.get()) {
return;
}
if (!executorService.isShutdown()) {
executorService.execute(() -> executeMutually(() -> {
while (!awaited.get()) {
if (logger.isInfoEnabled()) {
logger.info(" [Dubbo] Current Spring Boot Application is await...");
}
try {
condition.await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}));
}
}
protected void release() {
executeMutually(() -> {
while (awaited.compareAndSet(false, true)) {
if (logger.isInfoEnabled()) {
logger.info(" [Dubbo] Current Spring Boot Application is about to shutdown...");
}
condition.signalAll();
// @since 2.7.8 method shutdown() is combined into the method release()
shutdown();
}
});
}
private void shutdown() {
if (!executorService.isShutdown()) {
// Shutdown executorService
executorService.shutdown();
}
}
private void executeMutually(Runnable runnable) {
try {
lock.lock();
runnable.run();
} finally {
lock.unlock();
}
}
}

View File

@ -0,0 +1,121 @@
/*
* 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.spring.boot.context.event;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.spring.context.annotation.EnableDubboConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.Ordered;
import org.springframework.core.env.Environment;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.springframework.beans.factory.BeanFactoryUtils.beanNamesForTypeIncludingAncestors;
import static org.springframework.context.ConfigurableApplicationContext.ENVIRONMENT_BEAN_NAME;
/**
* The {@link ApplicationListener} class for Dubbo Config {@link BeanDefinition Bean Definition} to resolve conflict
* @see BeanDefinition
* @see ApplicationListener
* @since 2.7.5
*/
public class DubboConfigBeanDefinitionConflictApplicationListener implements ApplicationListener<ContextRefreshedEvent>,
Ordered {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
ApplicationContext applicationContext = event.getApplicationContext();
BeanDefinitionRegistry registry = getBeanDefinitionRegistry(applicationContext);
resolveUniqueApplicationConfigBean(registry, applicationContext);
}
private BeanDefinitionRegistry getBeanDefinitionRegistry(ApplicationContext applicationContext) {
AutowireCapableBeanFactory beanFactory = applicationContext.getAutowireCapableBeanFactory();
if (beanFactory instanceof BeanDefinitionRegistry) {
return (BeanDefinitionRegistry) beanFactory;
}
throw new IllegalStateException("");
}
/**
* Resolve the unique {@link ApplicationConfig} Bean
* @param registry {@link BeanDefinitionRegistry} instance
* @param beanFactory {@link ConfigurableListableBeanFactory} instance
* @see EnableDubboConfig
*/
private void resolveUniqueApplicationConfigBean(BeanDefinitionRegistry registry, ListableBeanFactory beanFactory) {
String[] beansNames = beanNamesForTypeIncludingAncestors(beanFactory, ApplicationConfig.class);
if (beansNames.length < 2) { // If the number of ApplicationConfig beans is less than two, return immediately.
return;
}
Environment environment = beanFactory.getBean(ENVIRONMENT_BEAN_NAME, Environment.class);
// Remove ApplicationConfig Beans that are configured by "dubbo.application.*"
Stream.of(beansNames)
.filter(beansName -> isConfiguredApplicationConfigBeanName(environment, beansName))
.forEach(registry::removeBeanDefinition);
beansNames = beanNamesForTypeIncludingAncestors(beanFactory, ApplicationConfig.class);
if (beansNames.length > 1) {
throw new IllegalStateException(String.format("There are more than one instances of %s, whose bean definitions : %s",
ApplicationConfig.class.getSimpleName(),
Stream.of(beansNames)
.map(registry::getBeanDefinition)
.collect(Collectors.toList()))
);
}
}
private boolean isConfiguredApplicationConfigBeanName(Environment environment, String beanName) {
boolean removed = BeanFactoryUtils.isGeneratedBeanName(beanName)
// Dubbo ApplicationConfig id as bean name
|| Objects.equals(beanName, environment.getProperty("dubbo.application.id"));
if (removed) {
if (logger.isDebugEnabled()) {
logger.debug("The {} bean [ name : {} ] has been removed!", ApplicationConfig.class.getSimpleName(), beanName);
}
}
return removed;
}
@Override
public int getOrder() {
return LOWEST_PRECEDENCE;
}
}

View File

@ -0,0 +1,79 @@
/*
* 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.spring.boot.context.event;
import org.apache.dubbo.common.utils.ConfigUtils;
import org.apache.dubbo.config.AbstractConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import java.util.SortedMap;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DEFAULT_OVERRIDE_CONFIG_PROPERTY_VALUE;
import static org.apache.dubbo.spring.boot.util.DubboUtils.OVERRIDE_CONFIG_FULL_PROPERTY_NAME;
import static org.apache.dubbo.spring.boot.util.DubboUtils.filterDubboProperties;
/**
* {@link ApplicationListener} to override the dubbo properties from {@link Environment}into
* {@link ConfigUtils#getProperties() Dubbo Config}.
* {@link AbstractConfig Dubbo Config} on {@link ApplicationEnvironmentPreparedEvent}.
* <p>
*
* @see ConfigUtils
* @since 2.7.0
*/
@Order // LOWEST_PRECEDENCE Make sure last execution
public class OverrideDubboConfigApplicationListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {
@Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
/**
* Gets Logger After LoggingSystem configuration ready
* @see LoggingApplicationListener
*/
final Logger logger = LoggerFactory.getLogger(getClass());
ConfigurableEnvironment environment = event.getEnvironment();
boolean override = environment.getProperty(OVERRIDE_CONFIG_FULL_PROPERTY_NAME, boolean.class,
DEFAULT_OVERRIDE_CONFIG_PROPERTY_VALUE);
if (override) {
SortedMap<String, Object> dubboProperties = filterDubboProperties(environment);
ConfigUtils.getProperties().putAll(dubboProperties);
if (logger.isInfoEnabled()) {
logger.info("Dubbo Config was overridden by externalized configuration {}", dubboProperties);
}
} else {
if (logger.isInfoEnabled()) {
logger.info("Disable override Dubbo Config caused by property {} = {}", OVERRIDE_CONFIG_FULL_PROPERTY_NAME, override);
}
}
}
}

View File

@ -0,0 +1,94 @@
/*
* 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.spring.boot.context.event;
import org.apache.dubbo.common.Version;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import java.util.concurrent.atomic.AtomicBoolean;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_GITHUB_URL;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_MAILING_LIST;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_SPRING_BOOT_GITHUB_URL;
import static org.apache.dubbo.spring.boot.util.DubboUtils.LINE_SEPARATOR;
/**
* Dubbo Welcome Logo {@link ApplicationListener}
*
* @see ApplicationListener
* @since 2.7.0
*/
@Order(Ordered.HIGHEST_PRECEDENCE + 20 + 1) // After LoggingApplicationListener#DEFAULT_ORDER
public class WelcomeLogoApplicationListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {
private static AtomicBoolean processed = new AtomicBoolean(false);
@Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
// Skip if processed before, prevent duplicated execution in Hierarchical ApplicationContext
if (processed.get()) {
return;
}
/**
* Gets Logger After LoggingSystem configuration ready
* @see LoggingApplicationListener
*/
final Logger logger = LoggerFactory.getLogger(getClass());
String bannerText = buildBannerText();
if (logger.isInfoEnabled()) {
logger.info(bannerText);
} else {
System.out.print(bannerText);
}
// mark processed to be true
processed.compareAndSet(false, true);
}
String buildBannerText() {
StringBuilder bannerTextBuilder = new StringBuilder();
bannerTextBuilder
.append(LINE_SEPARATOR)
.append(LINE_SEPARATOR)
.append(" :: Dubbo Spring Boot (v").append(Version.getVersion(getClass(), Version.getVersion())).append(") : ")
.append(DUBBO_SPRING_BOOT_GITHUB_URL)
.append(LINE_SEPARATOR)
.append(" :: Dubbo (v").append(Version.getVersion()).append(") : ")
.append(DUBBO_GITHUB_URL)
.append(LINE_SEPARATOR)
.append(" :: Discuss group : ")
.append(DUBBO_MAILING_LIST)
.append(LINE_SEPARATOR)
;
return bannerTextBuilder.toString();
}
}

View File

@ -0,0 +1,136 @@
/*
* 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.spring.boot.env;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_APPLICATION_NAME_PROPERTY;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_APPLICATION_QOS_ENABLE_PROPERTY;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_CONFIG_MULTIPLE_PROPERTY;
import static org.apache.dubbo.spring.boot.util.DubboUtils.SPRING_APPLICATION_NAME_PROPERTY;
/**
* The lowest precedence {@link EnvironmentPostProcessor} processes
* {@link SpringApplication#setDefaultProperties(Properties) Spring Boot default properties} for Dubbo
* as late as possible before {@link ConfigurableApplicationContext#refresh() application context refresh}.
*/
public class DubboDefaultPropertiesEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
/**
* The name of default {@link PropertySource} defined in SpringApplication#configurePropertySources method.
*/
public static final String PROPERTY_SOURCE_NAME = "defaultProperties";
/**
* The property name of "spring.main.allow-bean-definition-overriding".
* Please refer to: https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.1-Release-Notes#bean-overriding
*/
public static final String ALLOW_BEAN_DEFINITION_OVERRIDING_PROPERTY = "spring.main.allow-bean-definition-overriding";
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
MutablePropertySources propertySources = environment.getPropertySources();
Map<String, Object> defaultProperties = createDefaultProperties(environment);
if (!CollectionUtils.isEmpty(defaultProperties)) {
addOrReplace(propertySources, defaultProperties);
}
}
@Override
public int getOrder() {
return LOWEST_PRECEDENCE;
}
private Map<String, Object> createDefaultProperties(ConfigurableEnvironment environment) {
Map<String, Object> defaultProperties = new HashMap<>();
setDubboApplicationNameProperty(environment, defaultProperties);
setDubboConfigMultipleProperty(defaultProperties);
setDubboApplicationQosEnableProperty(defaultProperties);
setAllowBeanDefinitionOverriding(defaultProperties);
return defaultProperties;
}
private void setDubboApplicationNameProperty(Environment environment, Map<String, Object> defaultProperties) {
String springApplicationName = environment.getProperty(SPRING_APPLICATION_NAME_PROPERTY);
if (StringUtils.hasLength(springApplicationName)
&& !environment.containsProperty(DUBBO_APPLICATION_NAME_PROPERTY)) {
defaultProperties.put(DUBBO_APPLICATION_NAME_PROPERTY, springApplicationName);
}
}
private void setDubboConfigMultipleProperty(Map<String, Object> defaultProperties) {
defaultProperties.put(DUBBO_CONFIG_MULTIPLE_PROPERTY, Boolean.TRUE.toString());
}
private void setDubboApplicationQosEnableProperty(Map<String, Object> defaultProperties) {
defaultProperties.put(DUBBO_APPLICATION_QOS_ENABLE_PROPERTY, Boolean.FALSE.toString());
}
/**
* Set {@link #ALLOW_BEAN_DEFINITION_OVERRIDING_PROPERTY "spring.main.allow-bean-definition-overriding"} to be
* <code>true</code> as default.
*
* @param defaultProperties the default {@link Properties properties}
* @see #ALLOW_BEAN_DEFINITION_OVERRIDING_PROPERTY
* @since 2.7.1
*/
private void setAllowBeanDefinitionOverriding(Map<String, Object> defaultProperties) {
defaultProperties.put(ALLOW_BEAN_DEFINITION_OVERRIDING_PROPERTY, Boolean.TRUE.toString());
}
/**
* Copy from BusEnvironmentPostProcessor#addOrReplace(MutablePropertySources, Map)
*
* @param propertySources {@link MutablePropertySources}
* @param map Default Dubbo Properties
*/
private void addOrReplace(MutablePropertySources propertySources,
Map<String, Object> map) {
MapPropertySource target = null;
if (propertySources.contains(PROPERTY_SOURCE_NAME)) {
PropertySource<?> source = propertySources.get(PROPERTY_SOURCE_NAME);
if (source instanceof MapPropertySource) {
target = (MapPropertySource) source;
for (String key : map.keySet()) {
if (!target.containsProperty(key)) {
target.getSource().put(key, map.get(key));
}
}
}
}
if (target == null) {
target = new MapPropertySource(PROPERTY_SOURCE_NAME, map);
}
if (!propertySources.contains(PROPERTY_SOURCE_NAME)) {
propertySources.addLast(target);
}
}
}

View File

@ -0,0 +1,215 @@
/*
* 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.spring.boot.util;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationBeanPostProcessor;
import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceClassPostProcessor;
import org.apache.dubbo.config.spring.context.annotation.EnableDubboConfig;
import org.apache.dubbo.config.spring.context.properties.DubboConfigBinder;
import org.springframework.boot.context.ContextIdApplicationContextInitializer;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertyResolver;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
/**
* The utilities class for Dubbo
*
* @since 2.7.0
*/
public abstract class DubboUtils {
/**
* line separator
*/
public static final String LINE_SEPARATOR = System.getProperty("line.separator");
/**
* The separator of property name
*/
public static final String PROPERTY_NAME_SEPARATOR = ".";
/**
* The prefix of property name of Dubbo
*/
public static final String DUBBO_PREFIX = "dubbo";
/**
* The prefix of property name for Dubbo scan
*/
public static final String DUBBO_SCAN_PREFIX = DUBBO_PREFIX + PROPERTY_NAME_SEPARATOR + "scan" + PROPERTY_NAME_SEPARATOR;
/**
* The prefix of property name for Dubbo Config
*/
public static final String DUBBO_CONFIG_PREFIX = DUBBO_PREFIX + PROPERTY_NAME_SEPARATOR + "config" + PROPERTY_NAME_SEPARATOR;
/**
* The property name of base packages to scan
* <p>
* The default value is empty set.
*/
public static final String BASE_PACKAGES_PROPERTY_NAME = "base-packages";
/**
* The property name of multiple properties binding from externalized configuration
* <p>
* The default value is {@link #DEFAULT_MULTIPLE_CONFIG_PROPERTY_VALUE}
*
* @deprecated 2.7.8 It will be remove in the future, {@link EnableDubboConfig} instead
*/
@Deprecated
public static final String MULTIPLE_CONFIG_PROPERTY_NAME = "multiple";
/**
* The default value of multiple properties binding from externalized configuration
*
* @deprecated 2.7.8 It will be remove in the future
*/
@Deprecated
public static final boolean DEFAULT_MULTIPLE_CONFIG_PROPERTY_VALUE = true;
/**
* The property name of override Dubbo config
* <p>
* The default value is {@link #DEFAULT_OVERRIDE_CONFIG_PROPERTY_VALUE}
*/
public static final String OVERRIDE_CONFIG_FULL_PROPERTY_NAME = DUBBO_CONFIG_PREFIX + "override";
/**
* The default property value of override Dubbo config
*/
public static final boolean DEFAULT_OVERRIDE_CONFIG_PROPERTY_VALUE = true;
/**
* The github URL of Dubbo Spring Boot
*/
public static final String DUBBO_SPRING_BOOT_GITHUB_URL = "https://github.com/apache/dubbo-spring-boot-project";
/**
* The git URL of Dubbo Spring Boot
*/
public static final String DUBBO_SPRING_BOOT_GIT_URL = "https://github.com/apache/dubbo-spring-boot-project.git";
/**
* The issues of Dubbo Spring Boot
*/
public static final String DUBBO_SPRING_BOOT_ISSUES_URL = "https://github.com/apache/dubbo-spring-boot-project/issues";
/**
* The github URL of Dubbo
*/
public static final String DUBBO_GITHUB_URL = "https://github.com/apache/dubbo";
/**
* The google group URL of Dubbo
*/
public static final String DUBBO_MAILING_LIST = "dev@dubbo.apache.org";
/**
* The bean name of Relaxed-binding {@link DubboConfigBinder}
*/
public static final String RELAXED_DUBBO_CONFIG_BINDER_BEAN_NAME = "relaxedDubboConfigBinder";
/**
* The bean name of {@link PropertyResolver} for {@link ServiceAnnotationBeanPostProcessor}'s base-packages
*
* @deprecated 2.7.8 It will be remove in the future, please use {@link #BASE_PACKAGES_BEAN_NAME}
*/
@Deprecated
public static final String BASE_PACKAGES_PROPERTY_RESOLVER_BEAN_NAME = "dubboScanBasePackagesPropertyResolver";
/**
* The bean name of {@link Set} presenting {@link ServiceClassPostProcessor}'s base-packages
*
* @since 2.7.8
*/
public static final String BASE_PACKAGES_BEAN_NAME = "dubbo-service-class-base-packages";
/**
* The property name of Spring Application
*
* @see ContextIdApplicationContextInitializer
* @since 2.7.1
*/
public static final String SPRING_APPLICATION_NAME_PROPERTY = "spring.application.name";
/**
* The property id of {@link ApplicationConfig} Bean
*
* @see EnableDubboConfig
* @since 2.7.1
*/
public static final String DUBBO_APPLICATION_ID_PROPERTY = "dubbo.application.id";
/**
* The property name of {@link ApplicationConfig}
*
* @see EnableDubboConfig
* @since 2.7.1
*/
public static final String DUBBO_APPLICATION_NAME_PROPERTY = "dubbo.application.name";
/**
* The property name of {@link ApplicationConfig#getQosEnable() application's QOS enable}
*
* @since 2.7.1
*/
public static final String DUBBO_APPLICATION_QOS_ENABLE_PROPERTY = "dubbo.application.qos-enable";
/**
* The property name of {@link EnableDubboConfig#multiple() @EnableDubboConfig.multiple()}
*
* @since 2.7.1
*/
public static final String DUBBO_CONFIG_MULTIPLE_PROPERTY = "dubbo.config.multiple";
/**
* Filters Dubbo Properties from {@link ConfigurableEnvironment}
*
* @param environment {@link ConfigurableEnvironment}
* @return Read-only SortedMap
*/
public static SortedMap<String, Object> filterDubboProperties(ConfigurableEnvironment environment) {
SortedMap<String, Object> dubboProperties = new TreeMap<>();
Map<String, Object> properties = EnvironmentUtils.extractProperties(environment);
for (Map.Entry<String, Object> entry : properties.entrySet()) {
String propertyName = entry.getKey();
if (propertyName.startsWith(DUBBO_PREFIX + PROPERTY_NAME_SEPARATOR)
&& entry.getValue() != null) {
dubboProperties.put(propertyName, environment.resolvePlaceholders(entry.getValue().toString()));
}
}
return Collections.unmodifiableSortedMap(dubboProperties);
}
}

View File

@ -0,0 +1,114 @@
/*
* 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.spring.boot.util;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import org.springframework.util.ObjectUtils;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* The utilities class for {@link Environment}
*
* @see Environment
* @since 2.7.0
*/
public abstract class EnvironmentUtils {
/**
* Extras The properties from {@link ConfigurableEnvironment}
*
* @param environment {@link ConfigurableEnvironment}
* @return Read-only Map
*/
public static Map<String, Object> extractProperties(ConfigurableEnvironment environment) {
return Collections.unmodifiableMap(doExtraProperties(environment));
}
// /**
// * Gets {@link PropertySource} Map , the {@link PropertySource#getName()} as key
// *
// * @param environment {@link ConfigurableEnvironment}
// * @return Read-only Map
// */
// public static Map<String, PropertySource<?>> getPropertySources(ConfigurableEnvironment environment) {
// return Collections.unmodifiableMap(doGetPropertySources(environment));
// }
private static Map<String, Object> doExtraProperties(ConfigurableEnvironment environment) {
Map<String, Object> properties = new LinkedHashMap<>(); // orderly
Map<String, PropertySource<?>> map = doGetPropertySources(environment);
for (PropertySource<?> source : map.values()) {
if (source instanceof EnumerablePropertySource) {
EnumerablePropertySource propertySource = (EnumerablePropertySource) source;
String[] propertyNames = propertySource.getPropertyNames();
if (ObjectUtils.isEmpty(propertyNames)) {
continue;
}
for (String propertyName : propertyNames) {
if (!properties.containsKey(propertyName)) { // put If absent
properties.put(propertyName, propertySource.getProperty(propertyName));
}
}
}
}
return properties;
}
private static Map<String, PropertySource<?>> doGetPropertySources(ConfigurableEnvironment environment) {
Map<String, PropertySource<?>> map = new LinkedHashMap<String, PropertySource<?>>();
MutablePropertySources sources = environment.getPropertySources();
for (PropertySource<?> source : sources) {
extract("", map, source);
}
return map;
}
private static void extract(String root, Map<String, PropertySource<?>> map,
PropertySource<?> source) {
if (source instanceof CompositePropertySource) {
for (PropertySource<?> nest : ((CompositePropertySource) source)
.getPropertySources()) {
extract(source.getName() + ":", map, nest);
}
} else {
map.put(root + source.getName(), source);
}
}
}

View File

@ -0,0 +1,12 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.apache.dubbo.spring.boot.autoconfigure.DubboAutoConfiguration,\
org.apache.dubbo.spring.boot.autoconfigure.DubboRelaxedBindingAutoConfiguration
org.springframework.context.ApplicationListener=\
org.apache.dubbo.spring.boot.context.event.OverrideDubboConfigApplicationListener,\
org.apache.dubbo.spring.boot.context.event.DubboConfigBeanDefinitionConflictApplicationListener,\
org.apache.dubbo.spring.boot.context.event.WelcomeLogoApplicationListener,\
org.apache.dubbo.spring.boot.context.event.AwaitingNonWebApplicationListener
org.springframework.boot.env.EnvironmentPostProcessor=\
org.apache.dubbo.spring.boot.env.DubboDefaultPropertiesEnvironmentPostProcessor
org.springframework.context.ApplicationContextInitializer=\
org.apache.dubbo.spring.boot.context.DubboApplicationContextInitializer

View File

@ -0,0 +1,53 @@
/*
* 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.spring.boot;
import org.apache.dubbo.spring.boot.autoconfigure.CompatibleDubboAutoConfigurationTest;
import org.apache.dubbo.spring.boot.autoconfigure.CompatibleDubboAutoConfigurationTestWithoutProperties;
import org.apache.dubbo.spring.boot.autoconfigure.DubboAutoConfigurationOnMultipleConfigTest;
import org.apache.dubbo.spring.boot.autoconfigure.DubboAutoConfigurationOnSingleConfigTest;
import org.apache.dubbo.spring.boot.autoconfigure.RelaxedDubboConfigBinderTest;
import org.apache.dubbo.spring.boot.context.event.AwaitingNonWebApplicationListenerTest;
import org.apache.dubbo.spring.boot.context.event.DubboConfigBeanDefinitionConflictApplicationListenerTest;
import org.apache.dubbo.spring.boot.context.event.OverrideDubboConfigApplicationListenerDisableTest;
import org.apache.dubbo.spring.boot.context.event.OverrideDubboConfigApplicationListenerTest;
import org.apache.dubbo.spring.boot.context.event.WelcomeLogoApplicationListenerTest;
import org.apache.dubbo.spring.boot.env.DubboDefaultPropertiesEnvironmentPostProcessorTest;
import org.apache.dubbo.spring.boot.util.DubboUtilsTest;
import org.apache.dubbo.spring.boot.util.EnvironmentUtilsTest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({
CompatibleDubboAutoConfigurationTest.class,
CompatibleDubboAutoConfigurationTestWithoutProperties.class,
DubboAutoConfigurationOnMultipleConfigTest.class,
DubboAutoConfigurationOnSingleConfigTest.class,
RelaxedDubboConfigBinderTest.class,
AwaitingNonWebApplicationListenerTest.class,
DubboConfigBeanDefinitionConflictApplicationListenerTest.class,
OverrideDubboConfigApplicationListenerDisableTest.class,
OverrideDubboConfigApplicationListenerTest.class,
WelcomeLogoApplicationListenerTest.class,
DubboDefaultPropertiesEnvironmentPostProcessorTest.class,
DubboUtilsTest.class,
EnvironmentUtilsTest.class
})
public class TestSuite {
}

View File

@ -0,0 +1,59 @@
/*
* 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.spring.boot.autoconfigure;
import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor;
import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceClassPostProcessor;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.PropertySource;
import org.springframework.test.context.junit4.SpringRunner;
/**
* {@link DubboAutoConfiguration} Test
* @see DubboAutoConfiguration
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {
CompatibleDubboAutoConfigurationTest.class
}, properties = {
"dubbo.scan.base-packages = org.apache.dubbo.spring.boot.autoconfigure"
})
@EnableAutoConfiguration
@PropertySource(value = "classpath:/META-INF/dubbo.properties")
public class CompatibleDubboAutoConfigurationTest {
@Autowired
private ObjectProvider<ServiceClassPostProcessor> serviceClassPostProcessor;
@Autowired
private ObjectProvider<ReferenceAnnotationBeanPostProcessor> referenceAnnotationBeanPostProcessor;
@Test
public void testBeans() {
Assert.assertNotNull(serviceClassPostProcessor);
Assert.assertNotNull(serviceClassPostProcessor.getIfAvailable());
Assert.assertNotNull(referenceAnnotationBeanPostProcessor);
Assert.assertNotNull(referenceAnnotationBeanPostProcessor.getIfAvailable());
}
}

View File

@ -0,0 +1,64 @@
/*
* 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.spring.boot.autoconfigure;
import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor;
import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationBeanPostProcessor;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/**
* {@link DubboAutoConfiguration} Test
*
* @see DubboAutoConfiguration
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = CompatibleDubboAutoConfigurationTestWithoutProperties.class)
@EnableAutoConfiguration
public class CompatibleDubboAutoConfigurationTestWithoutProperties {
@Autowired(required = false)
private ServiceAnnotationBeanPostProcessor serviceAnnotationBeanPostProcessor;
@Autowired
private ReferenceAnnotationBeanPostProcessor referenceAnnotationBeanPostProcessor;
@Before
public void init() {
ApplicationModel.reset();
}
@After
public void destroy() {
ApplicationModel.reset();
}
@Test
public void testBeans() {
Assert.assertNull(serviceAnnotationBeanPostProcessor);
Assert.assertNotNull(referenceAnnotationBeanPostProcessor);
}
}

View File

@ -0,0 +1,277 @@
/*
* 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.spring.boot.autoconfigure;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ConsumerConfig;
import org.apache.dubbo.config.ModuleConfig;
import org.apache.dubbo.config.MonitorConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.ProviderConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.LinkedHashMap;
import java.util.Map;
import static org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors;
/**
* {@link DubboAutoConfiguration} Test On multiple Dubbo Configuration
*
* @since 2.7.0
*/
@RunWith(SpringRunner.class)
@TestPropertySource(
properties = {
"dubbo.applications.application1.NAME = dubbo-demo-application",
"dubbo.modules.module1.name = dubbo-demo-module",
"dubbo.registries.registry1.address = zookeeper://192.168.99.100:32770",
"dubbo.protocols.protocol1.name=dubbo",
"dubbo.protocols.protocol1.pORt=20880",
"dubbo.monitors.monitor1.Address=zookeeper://127.0.0.1:32770",
"dubbo.providers.provider1.host=127.0.0.1",
"dubbo.consumers.consumer1.client=netty",
"dubbo.config.multiple=true",
"dubbo.scan.basePackages=org.apache.dubbo.spring.boot.dubbo, org.apache.dubbo.spring.boot.condition"
}
)
@SpringBootTest(
classes = {
DubboAutoConfigurationOnMultipleConfigTest.class
}
)
@EnableAutoConfiguration
public class DubboAutoConfigurationOnMultipleConfigTest {
@Autowired
private Environment environment;
@Autowired
private ApplicationContext applicationContext;
/**
* {@link ApplicationConfig}
*/
@Autowired
@Qualifier("application1")
private ApplicationConfig application;
/**
* {@link ModuleConfig}
*/
@Autowired
@Qualifier("module1")
private ModuleConfig module;
/**
* {@link RegistryConfig}
*/
@Autowired
@Qualifier("registry1")
private RegistryConfig registry;
/**
* {@link ProtocolConfig}
*/
@Autowired
@Qualifier("protocol1")
private ProtocolConfig protocol;
/**
* {@link MonitorConfig}
*/
@Autowired
@Qualifier("monitor1")
private MonitorConfig monitor;
/**
* {@link ProviderConfig}
*/
@Autowired
@Qualifier("provider1")
private ProviderConfig provider;
/**
* {@link ConsumerConfig}
*/
@Autowired
@Qualifier("consumer1")
private ConsumerConfig consumer;
@Before
public void init() {
ApplicationModel.reset();
}
@After
public void destroy() {
ApplicationModel.reset();
}
@Autowired
private Map<String, ApplicationConfig> applications = new LinkedHashMap<>();
@Autowired
private Map<String, ModuleConfig> modules = new LinkedHashMap<>();
@Autowired
private Map<String, RegistryConfig> registries = new LinkedHashMap<>();
@Autowired
private Map<String, ProtocolConfig> protocols = new LinkedHashMap<>();
@Autowired
private Map<String, MonitorConfig> monitors = new LinkedHashMap<>();
@Autowired
private Map<String, ProviderConfig> providers = new LinkedHashMap<>();
@Autowired
private Map<String, ConsumerConfig> consumers = new LinkedHashMap<>();
@Test
public void testMultipleDubboConfigBindingProperties() {
Assert.assertEquals(1, applications.size());
Assert.assertEquals(1, modules.size());
Assert.assertEquals(1, registries.size());
Assert.assertEquals(1, protocols.size());
Assert.assertEquals(1, monitors.size());
Assert.assertEquals(1, providers.size());
Assert.assertEquals(1, consumers.size());
}
@Test
public void testApplicationContext() {
/**
* Multiple {@link ApplicationConfig}
*/
Map<String, ApplicationConfig> applications = beansOfTypeIncludingAncestors(applicationContext, ApplicationConfig.class);
Assert.assertEquals(1, applications.size());
/**
* Multiple {@link ModuleConfig}
*/
Map<String, ModuleConfig> modules = beansOfTypeIncludingAncestors(applicationContext, ModuleConfig.class);
Assert.assertEquals(1, modules.size());
/**
* Multiple {@link RegistryConfig}
*/
Map<String, RegistryConfig> registries = beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class);
Assert.assertEquals(1, registries.size());
/**
* Multiple {@link ProtocolConfig}
*/
Map<String, ProtocolConfig> protocols = beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class);
Assert.assertEquals(1, protocols.size());
/**
* Multiple {@link MonitorConfig}
*/
Map<String, MonitorConfig> monitors = beansOfTypeIncludingAncestors(applicationContext, MonitorConfig.class);
Assert.assertEquals(1, monitors.size());
/**
* Multiple {@link ProviderConfig}
*/
Map<String, ProviderConfig> providers = beansOfTypeIncludingAncestors(applicationContext, ProviderConfig.class);
Assert.assertEquals(1, providers.size());
/**
* Multiple {@link ConsumerConfig}
*/
Map<String, ConsumerConfig> consumers = beansOfTypeIncludingAncestors(applicationContext, ConsumerConfig.class);
Assert.assertEquals(1, consumers.size());
}
@Test
public void testApplicationConfig() {
Assert.assertEquals("dubbo-demo-application", application.getName());
}
@Test
public void testModuleConfig() {
Assert.assertEquals("dubbo-demo-module", module.getName());
}
@Test
public void testRegistryConfig() {
Assert.assertEquals("zookeeper://192.168.99.100:32770", registry.getAddress());
}
@Test
public void testMonitorConfig() {
Assert.assertEquals("zookeeper://127.0.0.1:32770", monitor.getAddress());
}
@Test
public void testProtocolConfig() {
Assert.assertEquals("dubbo", protocol.getName());
Assert.assertEquals(Integer.valueOf(20880), protocol.getPort());
}
@Test
public void testConsumerConfig() {
Assert.assertEquals("netty", consumer.getClient());
}
}

View File

@ -0,0 +1,151 @@
/*
* 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.spring.boot.autoconfigure;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ConsumerConfig;
import org.apache.dubbo.config.ModuleConfig;
import org.apache.dubbo.config.MonitorConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.ProviderConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
/**
* {@link DubboAutoConfiguration} Test On single Dubbo Configuration
*
* @since 2.7.0
*/
@RunWith(SpringRunner.class)
@TestPropertySource(
properties = {
"dubbo.application.name = dubbo-demo-application",
"dubbo.module.name = dubbo-demo-module",
"dubbo.registry.address = zookeeper://192.168.99.100:32770",
"dubbo.protocol.name=dubbo",
"dubbo.protocol.port=20880",
"dubbo.monitor.address=zookeeper://127.0.0.1:32770",
"dubbo.provider.host=127.0.0.1",
"dubbo.consumer.client=netty"
}
)
@SpringBootTest(
classes = {DubboAutoConfigurationOnSingleConfigTest.class}
)
@EnableAutoConfiguration
public class DubboAutoConfigurationOnSingleConfigTest {
@Autowired
private ApplicationConfig applicationConfig;
@Autowired
private ModuleConfig moduleConfig;
@Autowired
private RegistryConfig registryConfig;
@Autowired
private MonitorConfig monitorConfig;
@Autowired
private ProviderConfig providerConfig;
@Autowired
private ConsumerConfig consumerConfig;
@Autowired
private ProtocolConfig protocolConfig;
@Autowired
private Environment environment;
@Autowired
private ApplicationContext applicationContext;
@Before
public void init() {
ApplicationModel.reset();
}
@After
public void destroy() {
ApplicationModel.reset();
}
@Test
public void testApplicationConfig() {
Assert.assertEquals("dubbo-demo-application", applicationConfig.getName());
}
@Test
public void testModuleConfig() {
Assert.assertEquals("dubbo-demo-module", moduleConfig.getName());
}
@Test
public void testRegistryConfig() {
Assert.assertEquals("zookeeper://192.168.99.100:32770", registryConfig.getAddress());
}
@Test
public void testMonitorConfig() {
Assert.assertEquals("zookeeper://127.0.0.1:32770", monitorConfig.getAddress());
}
@Test
public void testProtocolConfig() {
Assert.assertEquals("dubbo", protocolConfig.getName());
Assert.assertEquals(Integer.valueOf(20880), protocolConfig.getPort());
}
@Test
public void testProviderConfig() {
Assert.assertEquals("127.0.0.1", providerConfig.getHost());
}
@Test
public void testConsumerConfig() {
Assert.assertEquals("netty", consumerConfig.getClient());
}
}

View File

@ -0,0 +1,90 @@
/*
* 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.spring.boot.autoconfigure;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.rpc.model.ApplicationModel;
import com.alibaba.spring.context.config.ConfigurationBeanBinder;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Map;
import static com.alibaba.spring.util.PropertySourcesUtils.getSubProperties;
/**
* {@link RelaxedDubboConfigBinder} Test
*/
@RunWith(SpringRunner.class)
@TestPropertySource(properties = {
"dubbo.application.NAME=hello",
"dubbo.application.owneR=world",
"dubbo.registry.Address=10.20.153.17",
"dubbo.protocol.pORt=20881",
"dubbo.service.invoke.timeout=2000",
})
@ContextConfiguration(classes = RelaxedDubboConfigBinder.class)
public class RelaxedDubboConfigBinderTest {
@Autowired
private ConfigurationBeanBinder dubboConfigBinder;
@Autowired
private ConfigurableEnvironment environment;
@Before
public void init() {
ApplicationModel.reset();
}
@After
public void destroy() {
ApplicationModel.reset();
}
@Test
public void testBinder() {
ApplicationConfig applicationConfig = new ApplicationConfig();
Map<String, Object> properties = getSubProperties(environment.getPropertySources(), "dubbo.application");
dubboConfigBinder.bind(properties, true, true, applicationConfig);
Assert.assertEquals("hello", applicationConfig.getName());
Assert.assertEquals("world", applicationConfig.getOwner());
RegistryConfig registryConfig = new RegistryConfig();
properties = getSubProperties(environment.getPropertySources(), "dubbo.registry");
dubboConfigBinder.bind(properties, true, true, registryConfig);
Assert.assertEquals("10.20.153.17", registryConfig.getAddress());
ProtocolConfig protocolConfig = new ProtocolConfig();
properties = getSubProperties(environment.getPropertySources(), "dubbo.protocol");
dubboConfigBinder.bind(properties, true, true, protocolConfig);
Assert.assertEquals(Integer.valueOf(20881), protocolConfig.getPort());
}
}

View File

@ -0,0 +1,75 @@
/*
* 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.spring.boot.context.event;
import org.apache.dubbo.common.lang.ShutdownHookCallbacks;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.springframework.boot.builder.SpringApplicationBuilder;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* {@link AwaitingNonWebApplicationListener} Test
*/
public class AwaitingNonWebApplicationListenerTest {
@Before
public void before() {
ApplicationModel.reset();
}
@After
public void after() {
ApplicationModel.reset();
}
@Test
public void init() {
AtomicBoolean awaited = AwaitingNonWebApplicationListener.getAwaited();
awaited.set(false);
}
@Test
public void testSingleContextNonWebApplication() {
new SpringApplicationBuilder(Object.class)
.web(false)
.run()
.close();
ShutdownHookCallbacks.INSTANCE.addCallback(() -> {
AtomicBoolean awaited = AwaitingNonWebApplicationListener.getAwaited();
Assert.assertTrue(awaited.get());
System.out.println("Callback...");
});
}
//
// @Test
// public void testMultipleContextNonWebApplication() {
// new SpringApplicationBuilder(Object.class)
// .parent(Object.class)
// .web(false)
// .run().close();
// AtomicBoolean awaited = AwaitingNonWebApplicationListener.getAwaited();
// Assert.assertFalse(awaited.get());
// }
}

View File

@ -0,0 +1,107 @@
/*
* 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.spring.boot.context.event;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.spring.context.annotation.EnableDubboConfig;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ImportResource;
import org.springframework.context.annotation.PropertySource;
import java.util.Map;
/**
* {@link DubboConfigBeanDefinitionConflictApplicationListener} Test
*
* @since 2.7.5
*/
public class DubboConfigBeanDefinitionConflictApplicationListenerTest {
private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
@Before
public void init() {
ApplicationModel.reset();
context.addApplicationListener(new DubboConfigBeanDefinitionConflictApplicationListener());
}
@After
public void destroy() {
context.close();
ApplicationModel.reset();
}
@Test
public void testNormalCase() {
System.setProperty("dubbo.application.name", "test-dubbo-application");
context.register(DubboConfig.class);
context.refresh();
ApplicationConfig applicationConfig = context.getBean(ApplicationConfig.class);
Assert.assertEquals("test-dubbo-application", applicationConfig.getName());
}
@Test
public void testDuplicatedConfigsCase() {
context.register(PropertySourceConfig.class, DubboConfig.class);
context.register(XmlConfig.class);
context.refresh();
Map<String, ApplicationConfig> beansMap = context.getBeansOfType(ApplicationConfig.class);
ApplicationConfig applicationConfig = beansMap.get("dubbo-consumer-2.7.x");
Assert.assertEquals(1, beansMap.size());
Assert.assertEquals("dubbo-consumer-2.7.x", applicationConfig.getName());
}
@Test(expected = IllegalStateException.class)
public void testFailedCase() {
context.register(ApplicationConfig.class);
testDuplicatedConfigsCase();
}
@EnableDubboConfig
static class DubboConfig {
}
@PropertySource("classpath:/META-INF/dubbo.properties")
static class PropertySourceConfig {
}
@ImportResource("classpath:/META-INF/spring/dubbo-context.xml")
static class XmlConfig {
}
}

View File

@ -0,0 +1,74 @@
/*
* 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.spring.boot.context.event;
import org.apache.dubbo.common.utils.ConfigUtils;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Properties;
/**
* {@link OverrideDubboConfigApplicationListener} Test
*
* @see OverrideDubboConfigApplicationListener
* @since 2.7.0
*/
@RunWith(SpringRunner.class)
@TestPropertySource(
properties = {
"dubbo.config.override = false",
"dubbo.application.name = dubbo-demo-application",
"dubbo.module.name = dubbo-demo-module",
}
)
@SpringBootTest(
classes = {OverrideDubboConfigApplicationListener.class}
)
public class OverrideDubboConfigApplicationListenerDisableTest {
@Before
public void init() {
ConfigUtils.getProperties().clear();
ApplicationModel.reset();
}
@After
public void destroy() {
ApplicationModel.reset();
}
@Test
public void testOnApplicationEvent() {
Properties properties = ConfigUtils.getProperties();
Assert.assertTrue(properties.isEmpty());
Assert.assertNull(properties.get("dubbo.application.name"));
Assert.assertNull(properties.get("dubbo.module.name"));
}
}

View File

@ -0,0 +1,75 @@
/*
* 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.spring.boot.context.event;
import org.apache.dubbo.common.utils.ConfigUtils;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Properties;
/**
* {@link OverrideDubboConfigApplicationListener} Test
*
* @see OverrideDubboConfigApplicationListener
* @since 2.7.0
*/
@RunWith(SpringRunner.class)
@TestPropertySource(
properties = {
"dubbo.application.name = dubbo-demo-application",
"dubbo.module.name = dubbo-demo-module",
"dubbo.registry.address = zookeeper://192.168.99.100:32770"
}
)
@SpringBootTest(
classes = {OverrideDubboConfigApplicationListener.class}
)
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
public class OverrideDubboConfigApplicationListenerTest {
@BeforeClass
public static void init() {
ApplicationModel.reset();
ConfigUtils.getProperties().clear();
}
@AfterClass
public static void destroy() {
ApplicationModel.reset();
}
@Test
public void testOnApplicationEvent() {
Properties properties = ConfigUtils.getProperties();
Assert.assertEquals("dubbo-demo-application", properties.get("dubbo.application.name"));
Assert.assertEquals("dubbo-demo-module", properties.get("dubbo.module.name"));
Assert.assertEquals("zookeeper://192.168.99.100:32770", properties.get("dubbo.registry.address"));
}
}

View File

@ -0,0 +1,48 @@
/*
* 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.spring.boot.context.event;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/**
* {@link WelcomeLogoApplicationListener} Test
*
* @see WelcomeLogoApplicationListener
* @since 2.7.0
*/
@RunWith(SpringRunner.class)
@SpringBootTest(
classes = {WelcomeLogoApplicationListener.class}
)
public class WelcomeLogoApplicationListenerTest {
@Autowired
private WelcomeLogoApplicationListener welcomeLogoApplicationListener;
@Test
public void testOnApplicationEvent() {
Assert.assertNotNull(welcomeLogoApplicationListener.buildBannerText());
}
}

View File

@ -0,0 +1,97 @@
/*
* 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.spring.boot.env;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.boot.SpringApplication;
import org.springframework.core.Ordered;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import org.springframework.mock.env.MockEnvironment;
import java.util.HashMap;
/**
* {@link DubboDefaultPropertiesEnvironmentPostProcessor} Test
*/
public class DubboDefaultPropertiesEnvironmentPostProcessorTest {
private DubboDefaultPropertiesEnvironmentPostProcessor instance =
new DubboDefaultPropertiesEnvironmentPostProcessor();
private SpringApplication springApplication = new SpringApplication();
@Test
public void testOrder() {
Assert.assertEquals(Ordered.LOWEST_PRECEDENCE, instance.getOrder());
}
@Test
public void testPostProcessEnvironment() {
MockEnvironment environment = new MockEnvironment();
// Case 1 : Not Any property
instance.postProcessEnvironment(environment, springApplication);
// Get PropertySources
MutablePropertySources propertySources = environment.getPropertySources();
// Nothing to change
PropertySource defaultPropertySource = propertySources.get("defaultProperties");
Assert.assertNotNull(defaultPropertySource);
Assert.assertEquals("true", defaultPropertySource.getProperty("dubbo.config.multiple"));
Assert.assertEquals("false", defaultPropertySource.getProperty("dubbo.application.qos-enable"));
// Case 2 : Only set property "spring.application.name"
environment.setProperty("spring.application.name", "demo-dubbo-application");
instance.postProcessEnvironment(environment, springApplication);
defaultPropertySource = propertySources.get("defaultProperties");
Object dubboApplicationName = defaultPropertySource.getProperty("dubbo.application.name");
Assert.assertEquals("demo-dubbo-application", dubboApplicationName);
// Case 3 : Only set property "dubbo.application.name"
// Rest environment
environment = new MockEnvironment();
propertySources = environment.getPropertySources();
environment.setProperty("dubbo.application.name", "demo-dubbo-application");
instance.postProcessEnvironment(environment, springApplication);
defaultPropertySource = propertySources.get("defaultProperties");
Assert.assertNotNull(defaultPropertySource);
dubboApplicationName = environment.getProperty("dubbo.application.name");
Assert.assertEquals("demo-dubbo-application", dubboApplicationName);
// Case 4 : If "defaultProperties" PropertySource is present in PropertySources
// Rest environment
environment = new MockEnvironment();
propertySources = environment.getPropertySources();
propertySources.addLast(new MapPropertySource("defaultProperties", new HashMap<String, Object>()));
environment.setProperty("spring.application.name", "demo-dubbo-application");
instance.postProcessEnvironment(environment, springApplication);
defaultPropertySource = propertySources.get("defaultProperties");
dubboApplicationName = defaultPropertySource.getProperty("dubbo.application.name");
Assert.assertEquals("demo-dubbo-application", dubboApplicationName);
// Case 5 : Rest dubbo.config.multiple and dubbo.application.qos-enable
environment = new MockEnvironment();
propertySources = environment.getPropertySources();
propertySources.addLast(new MapPropertySource("defaultProperties", new HashMap<String, Object>()));
environment.setProperty("dubbo.config.multiple", "false");
environment.setProperty("dubbo.application.qos-enable", "true");
instance.postProcessEnvironment(environment, springApplication);
Assert.assertEquals("false", environment.getProperty("dubbo.config.multiple"));
Assert.assertEquals("true", environment.getProperty("dubbo.application.qos-enable"));
}
}

View File

@ -0,0 +1,105 @@
/*
* 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.spring.boot.util;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.mock.env.MockEnvironment;
import java.util.SortedMap;
import static org.apache.dubbo.spring.boot.util.DubboUtils.BASE_PACKAGES_PROPERTY_NAME;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DEFAULT_MULTIPLE_CONFIG_PROPERTY_VALUE;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DEFAULT_OVERRIDE_CONFIG_PROPERTY_VALUE;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_APPLICATION_ID_PROPERTY;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_APPLICATION_NAME_PROPERTY;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_APPLICATION_QOS_ENABLE_PROPERTY;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_CONFIG_MULTIPLE_PROPERTY;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_CONFIG_PREFIX;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_GITHUB_URL;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_MAILING_LIST;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_PREFIX;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_SCAN_PREFIX;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_SPRING_BOOT_GITHUB_URL;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_SPRING_BOOT_GIT_URL;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_SPRING_BOOT_ISSUES_URL;
import static org.apache.dubbo.spring.boot.util.DubboUtils.MULTIPLE_CONFIG_PROPERTY_NAME;
import static org.apache.dubbo.spring.boot.util.DubboUtils.OVERRIDE_CONFIG_FULL_PROPERTY_NAME;
import static org.apache.dubbo.spring.boot.util.DubboUtils.SPRING_APPLICATION_NAME_PROPERTY;
import static org.apache.dubbo.spring.boot.util.DubboUtils.filterDubboProperties;
/**
* {@link DubboUtils} Test
*
* @see DubboUtils
* @since 2.7.0
*/
public class DubboUtilsTest {
@Test
public void testConstants() {
Assert.assertEquals("dubbo", DUBBO_PREFIX);
Assert.assertEquals("dubbo.scan.", DUBBO_SCAN_PREFIX);
Assert.assertEquals("base-packages", BASE_PACKAGES_PROPERTY_NAME);
Assert.assertEquals("dubbo.config.", DUBBO_CONFIG_PREFIX);
Assert.assertEquals("multiple", MULTIPLE_CONFIG_PROPERTY_NAME);
Assert.assertEquals("dubbo.config.override", OVERRIDE_CONFIG_FULL_PROPERTY_NAME);
Assert.assertEquals("https://github.com/apache/dubbo-spring-boot-project", DUBBO_SPRING_BOOT_GITHUB_URL);
Assert.assertEquals("https://github.com/apache/dubbo-spring-boot-project.git", DUBBO_SPRING_BOOT_GIT_URL);
Assert.assertEquals("https://github.com/apache/dubbo-spring-boot-project/issues", DUBBO_SPRING_BOOT_ISSUES_URL);
Assert.assertEquals("https://github.com/apache/dubbo", DUBBO_GITHUB_URL);
Assert.assertEquals("dev@dubbo.apache.org", DUBBO_MAILING_LIST);
Assert.assertEquals("spring.application.name", SPRING_APPLICATION_NAME_PROPERTY);
Assert.assertEquals("dubbo.application.id", DUBBO_APPLICATION_ID_PROPERTY);
Assert.assertEquals("dubbo.application.name", DUBBO_APPLICATION_NAME_PROPERTY);
Assert.assertEquals("dubbo.application.qos-enable", DUBBO_APPLICATION_QOS_ENABLE_PROPERTY);
Assert.assertEquals("dubbo.config.multiple", DUBBO_CONFIG_MULTIPLE_PROPERTY);
Assert.assertTrue(DEFAULT_MULTIPLE_CONFIG_PROPERTY_VALUE);
Assert.assertTrue(DEFAULT_OVERRIDE_CONFIG_PROPERTY_VALUE);
}
@Test
public void testFilterDubboProperties() {
MockEnvironment environment = new MockEnvironment();
environment.setProperty("message", "Hello,World");
environment.setProperty(DUBBO_CONFIG_PREFIX + MULTIPLE_CONFIG_PROPERTY_NAME, "true");
environment.setProperty(OVERRIDE_CONFIG_FULL_PROPERTY_NAME, "true");
SortedMap<String, Object> dubboProperties = filterDubboProperties(environment);
Assert.assertEquals("true", dubboProperties.get(DUBBO_CONFIG_PREFIX + MULTIPLE_CONFIG_PROPERTY_NAME));
Assert.assertEquals("true", dubboProperties.get(OVERRIDE_CONFIG_FULL_PROPERTY_NAME));
}
}

View File

@ -0,0 +1,63 @@
/*
* 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.spring.boot.util;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.StandardEnvironment;
import java.util.HashMap;
import java.util.Map;
/**
* {@link EnvironmentUtils} Test
*
* @see EnvironmentUtils
* @since 2.7.0
*/
public class EnvironmentUtilsTest {
@Test
public void testExtraProperties() {
System.setProperty("user.name", "mercyblitz");
StandardEnvironment environment = new StandardEnvironment();
Map<String, Object> map = new HashMap<>();
map.put("user.name", "Mercy");
MapPropertySource propertySource = new MapPropertySource("first", map);
CompositePropertySource compositePropertySource = new CompositePropertySource("comp");
compositePropertySource.addFirstPropertySource(propertySource);
MutablePropertySources propertySources = environment.getPropertySources();
propertySources.addFirst(compositePropertySource);
Map<String, Object> properties = EnvironmentUtils.extractProperties(environment);
Assert.assertEquals("Mercy", properties.get("user.name"));
}
}

View File

@ -0,0 +1 @@
dubbo.application.id = test-dubbo-application-id

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://dubbo.apache.org/schema/dubbo
http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<dubbo:application name="dubbo-consumer-2.7.x">
<dubbo:parameter key="qos.enable" value="false"/>
</dubbo:application>
</beans>

View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dubbo-spring-boot-compatible</artifactId>
<packaging>pom</packaging>
<description>Apache Dubbo Spring Boot Compatible for Spring Boot 1.x</description>
<properties>
<spring-boot.version>1.5.22.RELEASE</spring-boot.version>
</properties>
<modules>
<module>autoconfigure</module>
<module>actuator</module>
</modules>
<profiles>
<profile>
<!-- Spring Boot 1.4 -->
<id>spring-boot-1.4</id>
<properties>
<spring-boot.version>1.4.7.RELEASE</spring-boot.version>
</properties>
</profile>
</profiles>
</project>

View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dubbo-spring-boot-starter</artifactId>
<packaging>jar</packaging>
<description>Apache Dubbo Spring Boot Starter</description>
<dependencies>
<!-- Spring Boot dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-autoconfigure</artifactId>
<version>${revision}</version>
</dependency>
</dependencies>
</project>

193
dubbo-spring-boot/pom.xml Normal file
View File

@ -0,0 +1,193 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-parent</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>dubbo-spring-boot</artifactId>
<packaging>pom</packaging>
<description>Apache Dubbo Spring Boot Parent</description>
<modules>
<module>dubbo-spring-boot-actuator</module>
<module>dubbo-spring-boot-autoconfigure</module>
<module>dubbo-spring-boot-compatible</module>
<module>dubbo-spring-boot-starter</module>
</modules>
<properties>
<spring-boot.version>2.3.1.RELEASE</spring-boot.version>
<dubbo.version>${revision}</dubbo.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<repositories>
<repository>
<id>spring-milestone</id>
<name>Spring Milestone</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-snapshot</id>
<name>Spring Snapshot</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>rabbit-milestone</id>
<name>Rabbit Milestone</name>
<url>https://dl.bintray.com/rabbitmq/maven-milestones</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>https://repo.maven.apache.org/maven2</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-milestone</id>
<name>Spring Milestone</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-snapshot</id>
<name>Spring Snapshot</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
<profiles>
<profile>
<!-- Spring Boot 2.0 -->
<id>spring-boot-2.0</id>
<properties>
<spring-boot.version>2.0.9.RELEASE</spring-boot.version>
</properties>
</profile>
<profile>
<!-- Spring Boot 2.1 -->
<id>spring-boot-2.1</id>
<properties>
<spring-boot.version>2.1.15.RELEASE</spring-boot.version>
</properties>
</profile>
<profile>
<!-- Spring Boot 2.2 -->
<id>spring-boot-2.2</id>
<properties>
<spring-boot.version>2.2.8.RELEASE</spring-boot.version>
</properties>
</profile>
</profiles>
<build>
<!-- Used for packaging NOTICE & LICENSE to each sub-module jar-->
<resources>
<resource>
<directory>src/main/resources/</directory>
<filtering>false</filtering>
</resource>
<resource>
<directory>../</directory>
<targetPath>META-INF/</targetPath>
<filtering>false</filtering>
<includes>
<include>NOTICE</include>
<include>LICENSE</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>${maven_jar_version}</version>
<configuration>
<archive>
<addMavenDescriptor>true</addMavenDescriptor>
<index>true</index>
<manifest>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
<manifestEntries>
<Specification-Version>${project.version}</Specification-Version>
<Implementation-Version>${project.version}</Implementation-Version>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven_compiler_version}</version>
<configuration>
<compilerArgs>
<compilerArg>-parameters</compilerArg>
</compilerArgs>
<fork>true</fork>
<source>${java_source_version}</source>
<target>${java_target_version}</target>
<encoding>${file_encoding}</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -149,6 +149,7 @@
<module>dubbo-dependencies</module>
<module>dubbo-metadata</module>
<module>dubbo-build-tools</module>
<module>dubbo-spring-boot</module>
</modules>
<dependencyManagement>