diff --git a/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/config/ServiceScanHelper.java b/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/config/CloudScanHelper.java similarity index 75% rename from spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/config/ServiceScanHelper.java rename to spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/config/CloudScanHelper.java index deefb6f..9212ded 100644 --- a/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/config/ServiceScanHelper.java +++ b/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/config/CloudScanHelper.java @@ -10,6 +10,7 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.cloud.Cloud; import org.springframework.cloud.CloudFactory; +import org.springframework.cloud.app.ApplicationInstanceInfo; import org.springframework.cloud.config.java.ServiceScan; import org.springframework.cloud.service.GenericCloudServiceConnectorFactory; import org.springframework.cloud.service.ServiceInfo; @@ -21,7 +22,7 @@ import org.springframework.cloud.service.ServiceInfo; * * Usage: * Most applications should use either the Java config using {@link ServiceScan} annotation - * or XML config using <cloud:service-scan/> that introduce a bean of this type lgically + * or XML config using <cloud:service-scan/> that introduce a bean of this type logically * equivalent to: *
* <bean class="org.cloudfoundry.runtime.service.CloudServicesScanner"/>
@@ -44,9 +45,9 @@ import org.springframework.cloud.service.ServiceInfo;
* @author Ramnivas Laddad
*
*/
-public class ServiceScanHelper {
+public class CloudScanHelper {
private static final String CLOUD_FACTORY_BEAN_NAME = "__cloud_factory__";
- private static Logger logger = Logger.getLogger(ServiceScanHelper.class.getName());
+ private static Logger logger = Logger.getLogger(CloudScanHelper.class.getName());
private Cloud cloud;
@@ -58,6 +59,17 @@ public class ServiceScanHelper {
registerServiceBean(registry, serviceInfo);
}
}
+
+ public void registerApplicationInstanceBean(BeanDefinitionRegistry registry) {
+ initializeCloud(registry);
+
+ BeanDefinitionBuilder definitionBuilder =
+ BeanDefinitionBuilder.genericBeanDefinition(ApplicationInstanceInfoWrapper.class);
+ definitionBuilder.addConstructorArgValue(cloud);
+ definitionBuilder.getRawBeanDefinition().setAttribute(
+ "factoryBeanObjectType", ApplicationInstanceInfo.class);
+ registry.registerBeanDefinition("spring.cloud.appplicationInstanceInfo", definitionBuilder.getBeanDefinition());
+ }
private void initializeCloud(BeanDefinitionRegistry registry) {
if (cloud != null) {
@@ -113,5 +125,27 @@ public class ServiceScanHelper {
}
}
+ public static class ApplicationInstanceInfoWrapper implements FactoryBean {
+ private Cloud cloud;
+
+ public ApplicationInstanceInfoWrapper(Cloud cloud) {
+ this.cloud = cloud;
+ }
+
+ @Override
+ public ApplicationInstanceInfo getObject() throws Exception {
+ return cloud.getApplicationInstanceInfo();
+ }
+ @Override
+ public Class> getObjectType() {
+ return ApplicationInstanceInfo.class;
+ }
+
+ @Override
+ public boolean isSingleton() {
+ return true;
+ }
+
+ }
}
diff --git a/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/config/java/CloudScan.java b/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/config/java/CloudScan.java
new file mode 100644
index 0000000..813aee7
--- /dev/null
+++ b/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/config/java/CloudScan.java
@@ -0,0 +1,63 @@
+package org.springframework.cloud.config.java;
+
+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;
+
+import org.springframework.cloud.app.ApplicationInstanceInfo;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+
+/**
+ * Add this annotation to an @{@link Configuration} class to have a bean for each
+ * service bound to the app as well as one for {@link ApplicationInstanceInfo} added to
+ * the application context.
+ *
+ *
+ * @Configuration
+ * @CloudScan
+ * public class CloudConfiguration {
+ * // may (optionally) extend AbstractCloudConfiguration
+ * }
+ *
+ *
+ * This annotation is similar to @ComponentScan in Spring, which scans for classes
+ * with the @Component classes and creates a bean for each. @CloudScan, in the same
+ * spirit, scans services bound to the app and creates a bean for each. It also creates a bean
+ * of {@link ApplicationInstanceInfo} class to expose information about the application instance.
+ *
+ * Upon service scanning, if there is a unique bean of for service type, you can inject it
+ * using the following code (shows Redis, but the same scheme works for all services):
+ *
+ * @Autowired RedisConnectionFactory redisConnectionFactory;
+ *
+ *
+ * If there are more than one services of a type, you can use the @Qualifier annotation
+ * as in the following code:
+ *
+ * @Autowired @Qualifier("service-name1") RedisConnectionFactory redisConnectionFactory;
+ * @Autowired @Qualifier("service-name2") RedisConnectionFactory redisConnectionFactory;
+ *
+ *
+ * Similarly, application can have {@link ApplicationInstanceInfo} injected as follows:
+ *
+ * @Autowired ApplicationInstanceInfo applicationInstanceInfo;
+ *
+ *
+ * Note the difference between @{@link ServiceScan} and this annotation. While the former only
+ * adds beans for each bound service, the @{@link CloudScan} annotation also adds a
+ * bean for {@link ApplicationInstanceInfo}.
+ *
+ * @see ServiceScan
+ * @author Ramnivas Laddad
+ *
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+@Documented
+@Import(CloudScanConfiguration.class)
+public @interface CloudScan {
+
+}
diff --git a/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/config/java/CloudScanConfiguration.java b/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/config/java/CloudScanConfiguration.java
new file mode 100644
index 0000000..aa78f66
--- /dev/null
+++ b/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/config/java/CloudScanConfiguration.java
@@ -0,0 +1,25 @@
+package org.springframework.cloud.config.java;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.cloud.app.ApplicationInstanceInfo;
+import org.springframework.cloud.config.CloudScanHelper;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.type.AnnotationMetadata;
+
+/**
+ * Introduces beans for each bound service and one for {@link ApplicationInstanceInfo}
+ *
+ * @author Ramnivas Laddad
+ * @see CloudScan
+ */
+@Configuration
+public class CloudScanConfiguration extends ServiceScanConfiguration {
+ private CloudScanHelper helper = new CloudScanHelper();
+
+ @Override
+ public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) throws BeansException {
+ super.registerBeanDefinitions(importingClassMetadata, registry);
+ helper.registerApplicationInstanceBean(registry);
+ }
+}
diff --git a/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/config/java/ServiceScanConfiguration.java b/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/config/java/ServiceScanConfiguration.java
index d371f74..71eb208 100644
--- a/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/config/java/ServiceScanConfiguration.java
+++ b/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/config/java/ServiceScanConfiguration.java
@@ -2,7 +2,7 @@ package org.springframework.cloud.config.java;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
-import org.springframework.cloud.config.ServiceScanHelper;
+import org.springframework.cloud.config.CloudScanHelper;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
@@ -15,7 +15,7 @@ import org.springframework.core.type.AnnotationMetadata;
*/
@Configuration
public class ServiceScanConfiguration implements ImportBeanDefinitionRegistrar {
- private ServiceScanHelper helper = new ServiceScanHelper();
+ private CloudScanHelper helper = new CloudScanHelper();
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) throws BeansException {
diff --git a/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/config/xml/CloudNamespaceHandler.java b/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/config/xml/CloudNamespaceHandler.java
index 9c625a7..378c328 100644
--- a/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/config/xml/CloudNamespaceHandler.java
+++ b/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/config/xml/CloudNamespaceHandler.java
@@ -6,7 +6,7 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
-import org.springframework.cloud.config.ServiceScanHelper;
+import org.springframework.cloud.config.CloudScanHelper;
import org.w3c.dom.Element;
/**
@@ -47,7 +47,7 @@ public class CloudNamespaceHandler extends NamespaceHandlerSupport {
}
public static class ServiceScanBeanFactoryProcessor implements BeanFactoryPostProcessor {
- private ServiceScanHelper helper = new ServiceScanHelper();
+ private CloudScanHelper helper = new CloudScanHelper();
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
diff --git a/spring-cloud-spring-service-connector/src/test/java/org/springframework/cloud/config/java/CloudScanJavaConfigTest.java b/spring-cloud-spring-service-connector/src/test/java/org/springframework/cloud/config/java/CloudScanJavaConfigTest.java
new file mode 100644
index 0000000..548e1ab
--- /dev/null
+++ b/spring-cloud-spring-service-connector/src/test/java/org/springframework/cloud/config/java/CloudScanJavaConfigTest.java
@@ -0,0 +1,35 @@
+package org.springframework.cloud.config.java;
+
+import static org.junit.Assert.assertNotNull;
+
+import org.junit.Test;
+import org.springframework.cloud.app.ApplicationInstanceInfo;
+import org.springframework.cloud.config.AbstractCloudConfigServiceScanTest;
+import org.springframework.cloud.service.ServiceInfo;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * Test for the {@link CloudScan} annotation
+ *
+ * @author Ramnivas Laddad
+ *
+ */
+public class CloudScanJavaConfigTest extends AbstractCloudConfigServiceScanTest {
+ protected ApplicationContext getTestApplicationContext(ServiceInfo... serviceInfos) {
+ return getTestApplicationContext(CloudScanJavaConfigTestConfig.class, serviceInfos);
+ }
+
+ @Test
+ public void cloudScanIntroducesApplicationInstanceInfo() {
+ ApplicationContext testContext = getTestApplicationContext();
+
+ assertNotNull(testContext.getBean(ApplicationInstanceInfo.class));
+ }
+}
+
+@Configuration
+@CloudScan
+class CloudScanJavaConfigTestConfig {
+
+}
\ No newline at end of file