Extract metadata for includes and excludes
This commit is contained in:
2
pom.xml
2
pom.xml
@@ -47,7 +47,7 @@
|
|||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<java.version>1.7</java.version>
|
<java.version>1.6</java.version>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
</properties>
|
</properties>
|
||||||
|
|||||||
115
src/main/java/org/springframework/guice/GuiceModuleMetadata.java
Normal file
115
src/main/java/org/springframework/guice/GuiceModuleMetadata.java
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2013 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed 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.springframework.guice;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.DisposableBean;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
|
||||||
|
import org.springframework.core.type.classreading.MetadataReader;
|
||||||
|
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||||
|
import org.springframework.core.type.filter.TypeFilter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encapsulates some metadata about a Guice module that is to be created from the parent
|
||||||
|
* context of a <code>@Bean</code> of this type.
|
||||||
|
*
|
||||||
|
* @author Dave Syer
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class GuiceModuleMetadata {
|
||||||
|
|
||||||
|
private TypeFilter[] includeFilters;
|
||||||
|
|
||||||
|
private TypeFilter[] excludeFilters;
|
||||||
|
|
||||||
|
private Set<Class<?>> infrastructureTypes = new HashSet<Class<?>>();
|
||||||
|
|
||||||
|
{
|
||||||
|
infrastructureTypes.add(InitializingBean.class);
|
||||||
|
infrastructureTypes.add(DisposableBean.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory();
|
||||||
|
|
||||||
|
public GuiceModuleMetadata include(TypeFilter... filters) {
|
||||||
|
includeFilters = filters;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GuiceModuleMetadata exclude(TypeFilter... filters) {
|
||||||
|
excludeFilters = filters;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean matches(Class<?> type) {
|
||||||
|
|
||||||
|
if (infrastructureTypes.contains(type)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!visible(type)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (includeFilters != null) {
|
||||||
|
try {
|
||||||
|
MetadataReader reader = metadataReaderFactory.getMetadataReader(type
|
||||||
|
.getName());
|
||||||
|
for (TypeFilter filter : includeFilters) {
|
||||||
|
if (!filter.match(reader, metadataReaderFactory)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new IllegalStateException("Cannot read metadata for class " + type,
|
||||||
|
e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (excludeFilters != null) {
|
||||||
|
try {
|
||||||
|
MetadataReader reader = metadataReaderFactory.getMetadataReader(type
|
||||||
|
.getName());
|
||||||
|
for (TypeFilter filter : excludeFilters) {
|
||||||
|
if (filter.match(reader, metadataReaderFactory)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new IllegalStateException("Cannot read metadata for class " + type,
|
||||||
|
e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean visible(Class<?> type) {
|
||||||
|
Class<?> cls = type;
|
||||||
|
while (cls != null && cls != Object.class) {
|
||||||
|
if (!Modifier.isPublic(cls.getModifiers())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cls = cls.getDeclaringClass();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
package org.springframework.guice;
|
package org.springframework.guice;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||||
@@ -30,10 +31,17 @@ import com.google.inject.Provider;
|
|||||||
public class SpringModule implements Module {
|
public class SpringModule implements Module {
|
||||||
|
|
||||||
private DefaultListableBeanFactory beanFactory;
|
private DefaultListableBeanFactory beanFactory;
|
||||||
|
|
||||||
|
private GuiceModuleMetadata metadata = new GuiceModuleMetadata();
|
||||||
|
|
||||||
public SpringModule(GenericApplicationContext context) {
|
public SpringModule(GenericApplicationContext context) {
|
||||||
this.beanFactory = (DefaultListableBeanFactory) context
|
this.beanFactory = (DefaultListableBeanFactory) context
|
||||||
.getAutowireCapableBeanFactory();
|
.getAutowireCapableBeanFactory();
|
||||||
|
if (beanFactory.getBeanNamesForType(GuiceModuleMetadata.class).length>0) {
|
||||||
|
this.metadata = beanFactory.getBean(GuiceModuleMetadata.class);
|
||||||
|
} else if (BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, GuiceModuleMetadata.class).length>0) {
|
||||||
|
this.metadata = beanFactory.getBean(GuiceModuleMetadata.class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -45,22 +53,31 @@ public class SpringModule implements Module {
|
|||||||
Class<?> type = beanFactory.getType(name);
|
Class<?> type = beanFactory.getType(name);
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final Class<Object> cls = (Class<Object>) type;
|
final Class<Object> cls = (Class<Object>) type;
|
||||||
|
final String beanName = name;
|
||||||
Provider<Object> provider = new Provider<Object>() {
|
Provider<Object> provider = new Provider<Object>() {
|
||||||
@Override
|
@Override
|
||||||
public Object get() {
|
public Object get() {
|
||||||
return beanFactory.getBean(cls);
|
return beanFactory.getBean(beanName, cls);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (!cls.isInterface()) {
|
if (!cls.isInterface() && !ClassUtils.isCglibProxyClass(cls)) {
|
||||||
binder.bind(cls).toProvider(provider);
|
bindConditionally(binder, cls, provider);
|
||||||
}
|
}
|
||||||
for (Class<?> iface : ClassUtils.getAllInterfacesForClass(cls)) {
|
for (Class<?> iface : ClassUtils.getAllInterfacesForClass(cls)) {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Class<Object> unchecked = (Class<Object>) iface;
|
Class<Object> unchecked = (Class<Object>) iface;
|
||||||
binder.bind(unchecked).toProvider(provider);
|
bindConditionally(binder, unchecked, provider);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void bindConditionally(Binder binder, Class<Object> cls,
|
||||||
|
Provider<Object> provider) {
|
||||||
|
if (!metadata.matches(cls)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
binder.bind(cls).toProvider(provider);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013-2014 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed 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.springframework.guice;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.rules.ExpectedException;
|
||||||
|
import org.springframework.cache.annotation.Cacheable;
|
||||||
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||||
|
import org.springframework.core.type.filter.AssignableTypeFilter;
|
||||||
|
|
||||||
|
import com.google.inject.ConfigurationException;
|
||||||
|
import com.google.inject.Guice;
|
||||||
|
import com.google.inject.Injector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Dave Syer
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class SpringModuleMetadataTests {
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public ExpectedException expected = ExpectedException.none();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void twoConfigClasses() throws Exception {
|
||||||
|
Injector injector = createInjector(TestConfig.class, OtherConfig.class);
|
||||||
|
expected.expect(ConfigurationException.class);
|
||||||
|
assertNull(injector.getBinding(Service.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void includes() throws Exception {
|
||||||
|
Injector injector = createInjector(TestConfig.class, MetadataIncludesConfig.class);
|
||||||
|
expected.expect(ConfigurationException.class);
|
||||||
|
assertNull(injector.getBinding(Service.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void excludes() throws Exception {
|
||||||
|
Injector injector = createInjector(TestConfig.class, MetadataExcludesConfig.class);
|
||||||
|
expected.expect(ConfigurationException.class);
|
||||||
|
assertNull(injector.getBinding(Service.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Injector createInjector(Class<?>... config) {
|
||||||
|
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||||
|
context.register(config);
|
||||||
|
context.refresh();
|
||||||
|
Injector injector = Guice.createInjector(new SpringModule(context));
|
||||||
|
return injector;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Service {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static class MyService implements Service {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Foo {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public Foo(Service service) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
protected static class MetadataExcludesConfig {
|
||||||
|
@Bean
|
||||||
|
public GuiceModuleMetadata guiceModuleMetadata() {
|
||||||
|
GuiceModuleMetadata metadata = new GuiceModuleMetadata();
|
||||||
|
metadata.exclude(new AssignableTypeFilter(Service.class));
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
protected static class MetadataIncludesConfig {
|
||||||
|
@Bean
|
||||||
|
public GuiceModuleMetadata guiceModuleMetadata() {
|
||||||
|
GuiceModuleMetadata metadata = new GuiceModuleMetadata();
|
||||||
|
metadata.include(new AnnotationTypeFilter(Cacheable.class));
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public static class TestConfig {
|
||||||
|
@Bean
|
||||||
|
public Service service() {
|
||||||
|
return new MyService();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public static class OtherConfig {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -13,6 +13,8 @@
|
|||||||
|
|
||||||
package org.springframework.guice;
|
package org.springframework.guice;
|
||||||
|
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.rules.ExpectedException;
|
||||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
@@ -26,6 +28,9 @@ import com.google.inject.Injector;
|
|||||||
*/
|
*/
|
||||||
public class SpringModuleWiringTests extends AbstractCompleteWiringTests {
|
public class SpringModuleWiringTests extends AbstractCompleteWiringTests {
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public ExpectedException expected = ExpectedException.none();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Injector createInjector() {
|
protected Injector createInjector() {
|
||||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||||
@@ -40,6 +45,7 @@ public class SpringModuleWiringTests extends AbstractCompleteWiringTests {
|
|||||||
public Service service() {
|
public Service service() {
|
||||||
return new MyService();
|
return new MyService();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public Baz baz() {
|
public Baz baz() {
|
||||||
return new Baz(service());
|
return new Baz(service());
|
||||||
|
|||||||
Reference in New Issue
Block a user