Extract BeanFactoryProvider into convenience class

This commit is contained in:
Dave Syer
2017-06-01 10:04:40 +01:00
parent a01511f269
commit 490fc20cf7
3 changed files with 213 additions and 228 deletions

View File

@@ -1,200 +0,0 @@
package org.springframework.guice.module;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.inject.Inject;
import javax.inject.Provider;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Scopes;
import com.google.inject.spi.ProvisionListener;
import com.google.inject.util.Providers;
import org.junit.Test;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.util.AopTestUtils;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
public class SpringModuleGuiceBindingAwareTest {
@Test
public void testAllDependenciesInjectedAndLifeycleMethodsCalledOnce() {
Injector injector = Guice.createInjector(new SimpleGuiceModule(),
new SpringModule(new Provider<ConfigurableListableBeanFactory>() {
@Override
public ConfigurableListableBeanFactory get() {
PartiallyRefreshableApplicationContext context = new PartiallyRefreshableApplicationContext();
context.register(
GuiceProjectWithSpringLibraryTestSpringConfig.class);
context.getBeanFactory().registerSingleton("refreshListener",
new ContextRefreshingProvisionListener(context));
context.partialRefresh();
return context.getBeanFactory();
}
}));
// check guice provided bindings
assertNotNull(injector.getInstance(GuiceDependency1.class));
assertNotNull(injector.getInstance(IGuiceDependency1.class));
// check spring bindings as interface
ISpringBean springBean = injector.getInstance(ISpringBean.class);
assertNotNull(springBean);
assertNotNull(springBean.getDep1());
assertNotNull(springBean.getDep2());
assertNotNull(springBean.getDep3());
// invoke a method to make sure we aren't dealing with a lazy proxy
assertEquals("done", springBean.getDep1().doWork());
// check binding equality
assertSame(injector.getInstance(IGuiceDependency1.class),
AopTestUtils.getTargetObject(springBean.getDep1()));
assertSame(injector.getInstance(IGuiceDependency2.class),
AopTestUtils.getTargetObject(springBean.getDep2()));
assertSame(injector.getInstance(IGuiceDependency3.class),
AopTestUtils.getTargetObject(springBean.getDep3()));
}
static class SimpleGuiceModule extends AbstractModule {
@Override
protected void configure() {
bind(IGuiceDependency1.class).to(GuiceDependency1.class).in(Scopes.SINGLETON); // test
// normal
// binding
bind(IGuiceDependency2.class).toInstance(new IGuiceDependency2() {
}); // test instance binding
bind(IGuiceDependency3.class)
.toProvider(Providers.of(new IGuiceDependency3() {
})); // test provider binding
}
}
@Configuration
static class GuiceProjectWithSpringLibraryTestSpringConfig {
@Bean
public ISpringBean springDefinedSomething(IGuiceDependency1 dependency) {
return new SpringBean(dependency);
}
@Bean
public ApplicationListener<ApplicationEvent> eventListener(
final IGuiceDependency1 dependency) {
return new ApplicationListener<ApplicationEvent>() {
@Override
public void onApplicationEvent(ApplicationEvent event) {
dependency.doWork();
}
};
}
}
static interface IGuiceDependency1 {
String doWork();
}
static interface IGuiceDependency2 {
}
static interface IGuiceDependency3 {
}
static class GuiceDependency1 implements IGuiceDependency1 {
public String doWork() {
return "done";
}
}
static interface ISpringBean {
IGuiceDependency1 getDep1();
IGuiceDependency2 getDep2();
IGuiceDependency3 getDep3();
}
static class SpringBean implements ISpringBean {
private final IGuiceDependency1 dep1;
@Inject
private IGuiceDependency2 dep2;
@Inject
private IGuiceDependency3 dep3;
@Inject
public SpringBean(IGuiceDependency1 dependency) {
this.dep1 = dependency;
}
@Override
public IGuiceDependency1 getDep1() {
return dep1;
}
@Override
public IGuiceDependency2 getDep2() {
return dep2;
}
@Override
public IGuiceDependency3 getDep3() {
return dep3;
}
}
private static final class PartiallyRefreshableApplicationContext
extends AnnotationConfigApplicationContext {
private final AtomicBoolean partiallyRefreshed = new AtomicBoolean(false);
/*
* Initializes beanFactoryPostProcessors only to ensure that all BeanDefinition's
* are available
*/
void partialRefresh() {
invokeBeanFactoryPostProcessors(getBeanFactory());
}
@Override
protected void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory) {
if (partiallyRefreshed.compareAndSet(false, true)) {
super.invokeBeanFactoryPostProcessors(beanFactory);
}
}
}
private static final class ContextRefreshingProvisionListener
implements ProvisionListener {
private final ConfigurableApplicationContext context;
private final AtomicBoolean initialized = new AtomicBoolean(false);
private ContextRefreshingProvisionListener(
ConfigurableApplicationContext context) {
this.context = context;
}
@Override
public <T> void onProvision(ProvisionInvocation<T> provision) {
if (!initialized.getAndSet(true) && !context.isActive()) {
context.refresh();
}
provision.provision();
}
}
}

View File

@@ -1,31 +1,44 @@
/*
* Copyright 2016-2017 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.module;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import javax.inject.Inject;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.guice.annotation.EnableGuiceModules;
import org.springframework.guice.injector.SpringInjector;
import org.springframework.test.util.AopTestUtils;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Scopes;
import com.google.inject.util.Providers;
import org.junit.Test;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.util.AopTestUtils;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
public class SpringModuleGuiceBindingAwareTests {
@Test
public void testAllDependenciesInjectedAndLifeycleMethodsCalledOnce() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(GuiceProjectWithSpringLibraryTestSpringConfig.class, SimpleGuiceModule.class);
context.refresh();
Injector injector = new SpringInjector(context);
Injector injector = Guice.createInjector(new SimpleGuiceModule(),
new SpringModule(BeanFactoryProvider
.from(GuiceProjectWithSpringLibraryTestSpringConfig.class)));
// check guice provided bindings
assertNotNull(injector.getInstance(GuiceDependency1.class));
@@ -38,31 +51,34 @@ public class SpringModuleGuiceBindingAwareTests {
assertNotNull(springBean.getDep2());
assertNotNull(springBean.getDep3());
// invoke a method to make sure we aren't dealing with a lazy proxy
assertEquals("done", springBean.getDep1().doWork());
// check binding equality
assertSame(injector.getInstance(IGuiceDependency1.class), AopTestUtils.getTargetObject(springBean.getDep1()));
assertSame(injector.getInstance(IGuiceDependency2.class), AopTestUtils.getTargetObject(springBean.getDep2()));
assertSame(injector.getInstance(IGuiceDependency3.class), AopTestUtils.getTargetObject(springBean.getDep3()));
context.close();
assertSame(injector.getInstance(IGuiceDependency1.class),
AopTestUtils.getTargetObject(springBean.getDep1()));
assertSame(injector.getInstance(IGuiceDependency2.class),
AopTestUtils.getTargetObject(springBean.getDep2()));
assertSame(injector.getInstance(IGuiceDependency3.class),
AopTestUtils.getTargetObject(springBean.getDep3()));
}
static class SimpleGuiceModule extends AbstractModule {
@Override
protected void configure() {
// test normal binding
bind(IGuiceDependency1.class).to(GuiceDependency1.class).in(Scopes.SINGLETON);
// test instance binding
bind(IGuiceDependency1.class).to(GuiceDependency1.class).in(Scopes.SINGLETON); // test
// normal
// binding
bind(IGuiceDependency2.class).toInstance(new IGuiceDependency2() {
});
// test provider binding
bind(IGuiceDependency3.class).toProvider(Providers.of(new IGuiceDependency3() {
}));
}); // test instance binding
bind(IGuiceDependency3.class)
.toProvider(Providers.of(new IGuiceDependency3() {
})); // test provider binding
}
}
@Configuration
@EnableGuiceModules
static class GuiceProjectWithSpringLibraryTestSpringConfig {
@Bean
@@ -70,9 +86,20 @@ public class SpringModuleGuiceBindingAwareTests {
return new SpringBean(dependency);
}
@Bean
public ApplicationListener<ApplicationEvent> eventListener(
final IGuiceDependency1 dependency) {
return new ApplicationListener<ApplicationEvent>() {
@Override
public void onApplicationEvent(ApplicationEvent event) {
dependency.doWork();
}
};
}
}
static interface IGuiceDependency1 {
String doWork();
}
static interface IGuiceDependency2 {
@@ -82,6 +109,9 @@ public class SpringModuleGuiceBindingAwareTests {
}
static class GuiceDependency1 implements IGuiceDependency1 {
public String doWork() {
return "done";
}
}
static interface ISpringBean {
@@ -120,4 +150,5 @@ public class SpringModuleGuiceBindingAwareTests {
return dep3;
}
}
}