moving unit tests from .testsuite -> .context
+ created example.scannable package to house scannable components away from .context.annotation package + example.scannable will also lend itself to sharing via externals
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
|
||||
import org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
|
||||
/**
|
||||
* Unit tests for the {@link AnnotationScopeMetadataResolver} class.
|
||||
*
|
||||
* @author Rick Evans
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class AnnotationScopeMetadataResolverTests {
|
||||
|
||||
private AnnotationScopeMetadataResolver scopeMetadataResolver;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
this.scopeMetadataResolver = new AnnotationScopeMetadataResolver();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testThatResolveScopeMetadataDoesNotApplyScopedProxyModeToASingleton() {
|
||||
AnnotatedBeanDefinition bd = new AnnotatedGenericBeanDefinition(AnnotatedWithSingletonScope.class);
|
||||
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(bd);
|
||||
assertNotNull("resolveScopeMetadata(..) must *never* return null.", scopeMetadata);
|
||||
assertEquals(BeanDefinition.SCOPE_SINGLETON, scopeMetadata.getScopeName());
|
||||
assertEquals(ScopedProxyMode.NO, scopeMetadata.getScopedProxyMode());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testThatResolveScopeMetadataDoesApplyScopedProxyModeToAPrototype() {
|
||||
this.scopeMetadataResolver = new AnnotationScopeMetadataResolver(ScopedProxyMode.INTERFACES);
|
||||
AnnotatedBeanDefinition bd = new AnnotatedGenericBeanDefinition(AnnotatedWithPrototypeScope.class);
|
||||
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(bd);
|
||||
assertNotNull("resolveScopeMetadata(..) must *never* return null.", scopeMetadata);
|
||||
assertEquals(BeanDefinition.SCOPE_PROTOTYPE, scopeMetadata.getScopeName());
|
||||
assertEquals(ScopedProxyMode.INTERFACES, scopeMetadata.getScopedProxyMode());
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testCtorWithNullScopedProxyMode() {
|
||||
new AnnotationScopeMetadataResolver(null);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testSetScopeAnnotationTypeWithNullType() {
|
||||
scopeMetadataResolver.setScopeAnnotationType(null);
|
||||
}
|
||||
|
||||
|
||||
@Scope("singleton")
|
||||
private static final class AnnotatedWithSingletonScope {
|
||||
}
|
||||
|
||||
|
||||
@Scope("prototype")
|
||||
private static final class AnnotatedWithPrototypeScope {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.context.annotation;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||
import org.springframework.core.type.filter.AssignableTypeFilter;
|
||||
import org.springframework.core.type.filter.RegexPatternTypeFilter;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class ClassPathScanningCandidateComponentProviderTests {
|
||||
|
||||
private static final String TEST_BASE_PACKAGE =
|
||||
ClassPathScanningCandidateComponentProviderTests.class.getPackage().getName();
|
||||
|
||||
|
||||
@Test
|
||||
public void testWithDefaults() {
|
||||
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(true);
|
||||
Set<BeanDefinition> candidates = provider.findCandidateComponents(TEST_BASE_PACKAGE);
|
||||
assertEquals(9, candidates.size());
|
||||
assertTrue(containsBeanClass(candidates, NamedComponent.class));
|
||||
assertTrue(containsBeanClass(candidates, FooServiceImpl.class));
|
||||
assertTrue(containsBeanClass(candidates, StubFooDao.class));
|
||||
assertTrue(containsBeanClass(candidates, NamedStubDao.class));
|
||||
assertTrue(containsBeanClass(candidates, ServiceInvocationCounter.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithBogusBasePackage() {
|
||||
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(true);
|
||||
Set<BeanDefinition> candidates = provider.findCandidateComponents("bogus");
|
||||
assertEquals(0, candidates.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithPackageExcludeFilter() {
|
||||
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(true);
|
||||
provider.addExcludeFilter(new RegexPatternTypeFilter(Pattern.compile(TEST_BASE_PACKAGE + ".*")));
|
||||
Set<BeanDefinition> candidates = provider.findCandidateComponents(TEST_BASE_PACKAGE);
|
||||
assertEquals(0, candidates.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithNoFilters() {
|
||||
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
|
||||
Set<BeanDefinition> candidates = provider.findCandidateComponents(TEST_BASE_PACKAGE);
|
||||
assertEquals(0, candidates.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithComponentAnnotationOnly() {
|
||||
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
|
||||
provider.addIncludeFilter(new AnnotationTypeFilter(Component.class));
|
||||
provider.addExcludeFilter(new AnnotationTypeFilter(Repository.class));
|
||||
provider.addExcludeFilter(new AnnotationTypeFilter(Service.class));
|
||||
provider.addExcludeFilter(new AnnotationTypeFilter(Controller.class));
|
||||
Set<BeanDefinition> candidates = provider.findCandidateComponents(TEST_BASE_PACKAGE);
|
||||
assertEquals(6, candidates.size());
|
||||
assertTrue(containsBeanClass(candidates, NamedComponent.class));
|
||||
assertTrue(containsBeanClass(candidates, ServiceInvocationCounter.class));
|
||||
assertFalse(containsBeanClass(candidates, FooServiceImpl.class));
|
||||
assertFalse(containsBeanClass(candidates, StubFooDao.class));
|
||||
assertFalse(containsBeanClass(candidates, NamedStubDao.class));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testWithAspectAnnotationOnly() throws Exception {
|
||||
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
|
||||
provider.addIncludeFilter(new AnnotationTypeFilter(
|
||||
ClassUtils.forName("org.aspectj.lang.annotation.Aspect")));
|
||||
Set<BeanDefinition> candidates = provider.findCandidateComponents(TEST_BASE_PACKAGE);
|
||||
assertEquals(1, candidates.size());
|
||||
assertTrue(containsBeanClass(candidates, ServiceInvocationCounter.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithInterfaceType() {
|
||||
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
|
||||
provider.addIncludeFilter(new AssignableTypeFilter(FooDao.class));
|
||||
Set<BeanDefinition> candidates = provider.findCandidateComponents(TEST_BASE_PACKAGE);
|
||||
assertEquals(1, candidates.size());
|
||||
assertTrue(containsBeanClass(candidates, StubFooDao.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithClassType() {
|
||||
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
|
||||
provider.addIncludeFilter(new AssignableTypeFilter(MessageBean.class));
|
||||
Set<BeanDefinition> candidates = provider.findCandidateComponents(TEST_BASE_PACKAGE);
|
||||
assertEquals(1, candidates.size());
|
||||
assertTrue(containsBeanClass(candidates, MessageBean.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithMultipleMatchingFilters() {
|
||||
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
|
||||
provider.addIncludeFilter(new AnnotationTypeFilter(Component.class));
|
||||
provider.addIncludeFilter(new AssignableTypeFilter(FooServiceImpl.class));
|
||||
Set<BeanDefinition> candidates = provider.findCandidateComponents(TEST_BASE_PACKAGE);
|
||||
assertEquals(9, candidates.size());
|
||||
assertTrue(containsBeanClass(candidates, NamedComponent.class));
|
||||
assertTrue(containsBeanClass(candidates, ServiceInvocationCounter.class));
|
||||
assertTrue(containsBeanClass(candidates, FooServiceImpl.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExcludeTakesPrecedence() {
|
||||
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
|
||||
provider.addIncludeFilter(new AnnotationTypeFilter(Component.class));
|
||||
provider.addIncludeFilter(new AssignableTypeFilter(FooServiceImpl.class));
|
||||
provider.addExcludeFilter(new AssignableTypeFilter(FooService.class));
|
||||
Set<BeanDefinition> candidates = provider.findCandidateComponents(TEST_BASE_PACKAGE);
|
||||
assertEquals(8, candidates.size());
|
||||
assertTrue(containsBeanClass(candidates, NamedComponent.class));
|
||||
assertTrue(containsBeanClass(candidates, ServiceInvocationCounter.class));
|
||||
assertFalse(containsBeanClass(candidates, FooServiceImpl.class));
|
||||
}
|
||||
|
||||
private boolean containsBeanClass(Set<BeanDefinition> candidates, Class beanClass) {
|
||||
for (Iterator it = candidates.iterator(); it.hasNext();) {
|
||||
ScannedGenericBeanDefinition definition = (ScannedGenericBeanDefinition) it.next();
|
||||
if (beanClass.getName().equals(definition.getBeanClassName())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.context.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
public @interface CustomComponent {
|
||||
|
||||
}
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.context.annotation;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public interface FooDao {
|
||||
|
||||
String findFoo(int id);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.context.annotation;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public interface FooService {
|
||||
|
||||
String foo(int id);
|
||||
|
||||
boolean isInitCalled();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.context.annotation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.support.AbstractApplicationContext;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
@Service
|
||||
public class FooServiceImpl implements FooService {
|
||||
|
||||
@Autowired private FooDao fooDao;
|
||||
|
||||
@Autowired public BeanFactory beanFactory;
|
||||
|
||||
@Autowired public List<ListableBeanFactory> listableBeanFactory;
|
||||
|
||||
@Autowired public ResourceLoader resourceLoader;
|
||||
|
||||
@Autowired public ResourcePatternResolver resourcePatternResolver;
|
||||
|
||||
@Autowired public ApplicationEventPublisher eventPublisher;
|
||||
|
||||
@Autowired public MessageSource messageSource;
|
||||
|
||||
@Autowired public ApplicationContext context;
|
||||
|
||||
@Autowired public ConfigurableApplicationContext[] configurableContext;
|
||||
|
||||
@Autowired public AbstractApplicationContext genericContext;
|
||||
|
||||
private boolean initCalled = false;
|
||||
|
||||
@PostConstruct
|
||||
private void init() {
|
||||
if (this.initCalled) {
|
||||
throw new IllegalStateException("Init already called");
|
||||
}
|
||||
this.initCalled = true;
|
||||
}
|
||||
|
||||
public String foo(int id) {
|
||||
return this.fooDao.findFoo(id);
|
||||
}
|
||||
|
||||
public boolean isInitCalled() {
|
||||
return this.initCalled;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.context.annotation;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
@CustomComponent
|
||||
public class MessageBean {
|
||||
|
||||
private String message;
|
||||
|
||||
public MessageBean() {
|
||||
this.message = "DEFAULT MESSAGE";
|
||||
}
|
||||
|
||||
public MessageBean(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return this.message;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.context.annotation;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
@Component("myNamedComponent")
|
||||
public class NamedComponent {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.context.annotation;
|
||||
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
@Repository("myNamedDao")
|
||||
public class NamedStubDao {
|
||||
|
||||
public String find(int id) {
|
||||
return "bar";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.context.annotation;
|
||||
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Before;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
@Component
|
||||
@Aspect
|
||||
public class ServiceInvocationCounter {
|
||||
|
||||
private int useCount;
|
||||
|
||||
@Pointcut("execution(* org.springframework.context.annotation.FooService+.*(..))")
|
||||
public void serviceExecution() {}
|
||||
|
||||
@Before("serviceExecution()")
|
||||
public void countUse() {
|
||||
this.useCount++;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return this.useCount;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.context.annotation;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* JUnit-3.8-based unit test which verifies expected <em>init</em> and
|
||||
* <em>destroy</em> bean lifecycle behavior as requested in <a
|
||||
* href="http://opensource.atlassian.com/projects/spring/browse/SPR-3775"
|
||||
* target="_blank">SPR-3775</a>.
|
||||
* </p>
|
||||
* <p>
|
||||
* Specifically, combinations of the following are tested:
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li>{@link InitializingBean} & {@link DisposableBean} interfaces</li>
|
||||
* <li>Custom {@link RootBeanDefinition#getInitMethodName() init} &
|
||||
* {@link RootBeanDefinition#getDestroyMethodName() destroy} methods</li>
|
||||
* <li>JSR 250's {@link javax.annotation.PostConstruct @PostConstruct} &
|
||||
* {@link javax.annotation.PreDestroy @PreDestroy} annotations</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 2.5
|
||||
*/
|
||||
public class Spr3775InitDestroyLifecycleTests {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(Spr3775InitDestroyLifecycleTests.class);
|
||||
|
||||
/** LIFECYCLE_TEST_BEAN. */
|
||||
private static final String LIFECYCLE_TEST_BEAN = "lifecycleTestBean";
|
||||
|
||||
|
||||
private void debugMethods(Class<?> clazz, String category, List<String> methodNames) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(clazz.getSimpleName() + ": " + category + ": " + methodNames);
|
||||
}
|
||||
}
|
||||
|
||||
private void assertMethodOrdering(Class<?> clazz, String category, List<String> expectedMethods,
|
||||
List<String> actualMethods) {
|
||||
debugMethods(clazz, category, actualMethods);
|
||||
assertTrue("Verifying " + category + ": expected<" + expectedMethods + "> but got<" + actualMethods + ">.",
|
||||
ObjectUtils.nullSafeEquals(expectedMethods, actualMethods));
|
||||
}
|
||||
|
||||
private DefaultListableBeanFactory createBeanFactoryAndRegisterBean(final Class<?> beanClass,
|
||||
final String initMethodName, final String destroyMethodName) {
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition beanDefinition = new RootBeanDefinition(beanClass);
|
||||
beanDefinition.setInitMethodName(initMethodName);
|
||||
beanDefinition.setDestroyMethodName(destroyMethodName);
|
||||
beanFactory.addBeanPostProcessor(new CommonAnnotationBeanPostProcessor());
|
||||
beanFactory.registerBeanDefinition(LIFECYCLE_TEST_BEAN, beanDefinition);
|
||||
return beanFactory;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitDestroyMethods() {
|
||||
final Class<?> beanClass = InitDestroyBean.class;
|
||||
final DefaultListableBeanFactory beanFactory = createBeanFactoryAndRegisterBean(beanClass,
|
||||
"afterPropertiesSet", "destroy");
|
||||
final InitDestroyBean bean = (InitDestroyBean) beanFactory.getBean(LIFECYCLE_TEST_BEAN);
|
||||
assertMethodOrdering(beanClass, "init-methods", Arrays.asList("afterPropertiesSet"), bean.initMethods);
|
||||
beanFactory.destroySingletons();
|
||||
assertMethodOrdering(beanClass, "destroy-methods", Arrays.asList("destroy"), bean.destroyMethods);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitializingDisposableInterfaces() {
|
||||
final Class<?> beanClass = CustomInitializingDisposableBean.class;
|
||||
final DefaultListableBeanFactory beanFactory = createBeanFactoryAndRegisterBean(beanClass, "customInit",
|
||||
"customDestroy");
|
||||
final CustomInitializingDisposableBean bean = (CustomInitializingDisposableBean) beanFactory.getBean(LIFECYCLE_TEST_BEAN);
|
||||
assertMethodOrdering(beanClass, "init-methods", Arrays.asList("afterPropertiesSet", "customInit"),
|
||||
bean.initMethods);
|
||||
beanFactory.destroySingletons();
|
||||
assertMethodOrdering(beanClass, "destroy-methods", Arrays.asList("destroy", "customDestroy"),
|
||||
bean.destroyMethods);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitializingDisposableInterfacesWithShadowedMethods() {
|
||||
final Class<?> beanClass = InitializingDisposableWithShadowedMethodsBean.class;
|
||||
final DefaultListableBeanFactory beanFactory = createBeanFactoryAndRegisterBean(beanClass,
|
||||
"afterPropertiesSet", "destroy");
|
||||
final InitializingDisposableWithShadowedMethodsBean bean = (InitializingDisposableWithShadowedMethodsBean) beanFactory.getBean(LIFECYCLE_TEST_BEAN);
|
||||
assertMethodOrdering(beanClass, "init-methods", Arrays.asList("InitializingBean.afterPropertiesSet"),
|
||||
bean.initMethods);
|
||||
beanFactory.destroySingletons();
|
||||
assertMethodOrdering(beanClass, "destroy-methods", Arrays.asList("DisposableBean.destroy"), bean.destroyMethods);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJsr250Annotations() {
|
||||
final Class<?> beanClass = CustomAnnotatedInitDestroyBean.class;
|
||||
final DefaultListableBeanFactory beanFactory = createBeanFactoryAndRegisterBean(beanClass, "customInit",
|
||||
"customDestroy");
|
||||
final CustomAnnotatedInitDestroyBean bean = (CustomAnnotatedInitDestroyBean) beanFactory.getBean(LIFECYCLE_TEST_BEAN);
|
||||
assertMethodOrdering(beanClass, "init-methods", Arrays.asList("postConstruct", "afterPropertiesSet",
|
||||
"customInit"), bean.initMethods);
|
||||
beanFactory.destroySingletons();
|
||||
assertMethodOrdering(beanClass, "destroy-methods", Arrays.asList("preDestroy", "destroy", "customDestroy"),
|
||||
bean.destroyMethods);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJsr250AnnotationsWithShadowedMethods() {
|
||||
final Class<?> beanClass = CustomAnnotatedInitDestroyWithShadowedMethodsBean.class;
|
||||
final DefaultListableBeanFactory beanFactory = createBeanFactoryAndRegisterBean(beanClass, "customInit",
|
||||
"customDestroy");
|
||||
final CustomAnnotatedInitDestroyWithShadowedMethodsBean bean = (CustomAnnotatedInitDestroyWithShadowedMethodsBean) beanFactory.getBean(LIFECYCLE_TEST_BEAN);
|
||||
assertMethodOrdering(beanClass, "init-methods",
|
||||
Arrays.asList("@PostConstruct.afterPropertiesSet", "customInit"), bean.initMethods);
|
||||
beanFactory.destroySingletons();
|
||||
assertMethodOrdering(beanClass, "destroy-methods", Arrays.asList("@PreDestroy.destroy", "customDestroy"),
|
||||
bean.destroyMethods);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAllLifecycleMechanismsAtOnce() {
|
||||
final Class<?> beanClass = AllInOneBean.class;
|
||||
final DefaultListableBeanFactory beanFactory = createBeanFactoryAndRegisterBean(beanClass,
|
||||
"afterPropertiesSet", "destroy");
|
||||
final AllInOneBean bean = (AllInOneBean) beanFactory.getBean(LIFECYCLE_TEST_BEAN);
|
||||
assertMethodOrdering(beanClass, "init-methods", Arrays.asList("afterPropertiesSet"), bean.initMethods);
|
||||
beanFactory.destroySingletons();
|
||||
assertMethodOrdering(beanClass, "destroy-methods", Arrays.asList("destroy"), bean.destroyMethods);
|
||||
}
|
||||
|
||||
|
||||
public static class InitDestroyBean {
|
||||
|
||||
final List<String> initMethods = new ArrayList<String>();
|
||||
final List<String> destroyMethods = new ArrayList<String>();
|
||||
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
this.initMethods.add("afterPropertiesSet");
|
||||
}
|
||||
|
||||
public void destroy() throws Exception {
|
||||
this.destroyMethods.add("destroy");
|
||||
}
|
||||
}
|
||||
|
||||
public static class InitializingDisposableWithShadowedMethodsBean extends InitDestroyBean implements
|
||||
InitializingBean, DisposableBean {
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
this.initMethods.add("InitializingBean.afterPropertiesSet");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
this.destroyMethods.add("DisposableBean.destroy");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class CustomInitDestroyBean {
|
||||
|
||||
final List<String> initMethods = new ArrayList<String>();
|
||||
final List<String> destroyMethods = new ArrayList<String>();
|
||||
|
||||
public void customInit() throws Exception {
|
||||
this.initMethods.add("customInit");
|
||||
}
|
||||
|
||||
public void customDestroy() throws Exception {
|
||||
this.destroyMethods.add("customDestroy");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class CustomInitializingDisposableBean extends CustomInitDestroyBean
|
||||
implements InitializingBean, DisposableBean {
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
this.initMethods.add("afterPropertiesSet");
|
||||
}
|
||||
|
||||
public void destroy() throws Exception {
|
||||
this.destroyMethods.add("destroy");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class CustomAnnotatedInitDestroyBean extends CustomInitializingDisposableBean {
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct() throws Exception {
|
||||
this.initMethods.add("postConstruct");
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void preDestroy() throws Exception {
|
||||
this.destroyMethods.add("preDestroy");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class CustomAnnotatedInitDestroyWithShadowedMethodsBean extends CustomInitializingDisposableBean {
|
||||
|
||||
@PostConstruct
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
this.initMethods.add("@PostConstruct.afterPropertiesSet");
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
this.destroyMethods.add("@PreDestroy.destroy");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class AllInOneBean implements InitializingBean, DisposableBean {
|
||||
|
||||
final List<String> initMethods = new ArrayList<String>();
|
||||
final List<String> destroyMethods = new ArrayList<String>();
|
||||
|
||||
@PostConstruct
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
this.initMethods.add("afterPropertiesSet");
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void destroy() throws Exception {
|
||||
this.destroyMethods.add("destroy");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.context.annotation;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
@Repository
|
||||
@Qualifier("testing")
|
||||
public class StubFooDao implements FooDao {
|
||||
|
||||
public String findFoo(int id) {
|
||||
return "bar";
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user