Merge branch '3.2.x' into cleanup-3.2.x
* 3.2.x: Promote use of @PostConstruct and @PreDestroy @Scheduled provides String variants of fixedDelay, fixedRate, initialDelay for placeholder support Further preparations for 3.2.2 @Scheduled provides String variants of fixedDelay, fixedRate, initialDelay for placeholder support Folded a FactoryBean-specific check into predictBeanType now Fix Assert.instanceOf exception message Allow for ordering of mixed AspectJ before/after advices Minor javadoc and source layout polishing Fixed documentation for "depends-on" attribute "depends-on" attribute on lang namespace element actually respected at runtime now Allow for ordering of mixed AspectJ before/after advices
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright 2002-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.context.annotation;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Unit tests for SPR-8954, in which a custom {@link InstantiationAwareBeanPostProcessor}
|
||||
* forces the predicted type of a FactoryBean, effectively preventing retrieval of the
|
||||
* bean from calls to #getBeansOfType(FactoryBean.class). The implementation of
|
||||
* {@link AbstractBeanFactory#isFactoryBean(String, RootBeanDefinition)} now ensures
|
||||
* that not only the predicted bean type is considered, but also the original bean
|
||||
* definition's beanClass.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class ConfigurationClassSpr8954Tests {
|
||||
|
||||
@Test
|
||||
public void repro() {
|
||||
AnnotationConfigApplicationContext bf = new AnnotationConfigApplicationContext();
|
||||
bf.registerBeanDefinition("fooConfig", new RootBeanDefinition(FooConfig.class));
|
||||
bf.getBeanFactory().addBeanPostProcessor(new PredictingBPP());
|
||||
bf.refresh();
|
||||
|
||||
assertThat(bf.getBean("foo"), instanceOf(Foo.class));
|
||||
assertThat(bf.getBean("&foo"), instanceOf(FooFactoryBean.class));
|
||||
|
||||
assertThat(bf.isTypeMatch("&foo", FactoryBean.class), is(true));
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
Map<String, FactoryBean> fbBeans = bf.getBeansOfType(FactoryBean.class);
|
||||
assertThat(1, equalTo(fbBeans.size()));
|
||||
assertThat("&foo", equalTo(fbBeans.keySet().iterator().next()));
|
||||
|
||||
Map<String, AnInterface> aiBeans = bf.getBeansOfType(AnInterface.class);
|
||||
assertThat(1, equalTo(aiBeans.size()));
|
||||
assertThat("&foo", equalTo(aiBeans.keySet().iterator().next()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findsBeansByTypeIfNotInstantiated() {
|
||||
AnnotationConfigApplicationContext bf = new AnnotationConfigApplicationContext();
|
||||
bf.registerBeanDefinition("fooConfig", new RootBeanDefinition(FooConfig.class));
|
||||
bf.getBeanFactory().addBeanPostProcessor(new PredictingBPP());
|
||||
bf.refresh();
|
||||
|
||||
assertThat(bf.isTypeMatch("&foo", FactoryBean.class), is(true));
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
Map<String, FactoryBean> fbBeans = bf.getBeansOfType(FactoryBean.class);
|
||||
assertThat(1, equalTo(fbBeans.size()));
|
||||
assertThat("&foo", equalTo(fbBeans.keySet().iterator().next()));
|
||||
|
||||
Map<String, AnInterface> aiBeans = bf.getBeansOfType(AnInterface.class);
|
||||
assertThat(1, equalTo(aiBeans.size()));
|
||||
assertThat("&foo", equalTo(aiBeans.keySet().iterator().next()));
|
||||
}
|
||||
|
||||
|
||||
static class FooConfig {
|
||||
|
||||
@Bean FooFactoryBean foo() {
|
||||
return new FooFactoryBean();
|
||||
}
|
||||
}
|
||||
|
||||
static class FooFactoryBean implements FactoryBean<Foo>, AnInterface {
|
||||
|
||||
@Override
|
||||
public Foo getObject() throws Exception {
|
||||
return new Foo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return Foo.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
interface AnInterface {
|
||||
}
|
||||
|
||||
static class Foo {
|
||||
}
|
||||
|
||||
interface PredictedType {
|
||||
}
|
||||
|
||||
static class PredictedTypeImpl implements PredictedType {
|
||||
}
|
||||
|
||||
static class PredictingBPP extends InstantiationAwareBeanPostProcessorAdapter {
|
||||
|
||||
@Override
|
||||
public Class<?> predictBeanType(Class<?> beanClass, String beanName) {
|
||||
return FactoryBean.class.isAssignableFrom(beanClass) ?
|
||||
PredictedType.class : null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
@@ -52,8 +53,7 @@ public class ScheduledAnnotationBeanPostProcessorTests {
|
||||
public void fixedDelayTask() {
|
||||
StaticApplicationContext context = new StaticApplicationContext();
|
||||
BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class);
|
||||
BeanDefinition targetDefinition = new RootBeanDefinition(
|
||||
ScheduledAnnotationBeanPostProcessorTests.FixedDelayTestBean.class);
|
||||
BeanDefinition targetDefinition = new RootBeanDefinition(FixedDelayTestBean.class);
|
||||
context.registerBeanDefinition("postProcessor", processorDefinition);
|
||||
context.registerBeanDefinition("target", targetDefinition);
|
||||
context.refresh();
|
||||
@@ -106,8 +106,7 @@ public class ScheduledAnnotationBeanPostProcessorTests {
|
||||
public void fixedRateTaskWithInitialDelay() {
|
||||
StaticApplicationContext context = new StaticApplicationContext();
|
||||
BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class);
|
||||
BeanDefinition targetDefinition = new RootBeanDefinition(
|
||||
ScheduledAnnotationBeanPostProcessorTests.FixedRateWithInitialDelayTestBean.class);
|
||||
BeanDefinition targetDefinition = new RootBeanDefinition(FixedRateWithInitialDelayTestBean.class);
|
||||
context.registerBeanDefinition("postProcessor", processorDefinition);
|
||||
context.registerBeanDefinition("target", targetDefinition);
|
||||
context.refresh();
|
||||
@@ -162,8 +161,7 @@ public class ScheduledAnnotationBeanPostProcessorTests {
|
||||
public void metaAnnotationWithFixedRate() {
|
||||
StaticApplicationContext context = new StaticApplicationContext();
|
||||
BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class);
|
||||
BeanDefinition targetDefinition = new RootBeanDefinition(
|
||||
ScheduledAnnotationBeanPostProcessorTests.MetaAnnotationFixedRateTestBean.class);
|
||||
BeanDefinition targetDefinition = new RootBeanDefinition(MetaAnnotationFixedRateTestBean.class);
|
||||
context.registerBeanDefinition("postProcessor", processorDefinition);
|
||||
context.registerBeanDefinition("target", targetDefinition);
|
||||
context.refresh();
|
||||
@@ -211,7 +209,7 @@ public class ScheduledAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void propertyPlaceholderWithCronExpression() {
|
||||
public void propertyPlaceholderWithCron() {
|
||||
String businessHoursCronExpression = "0 0 9-17 * * MON-FRI";
|
||||
StaticApplicationContext context = new StaticApplicationContext();
|
||||
BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class);
|
||||
@@ -219,8 +217,7 @@ public class ScheduledAnnotationBeanPostProcessorTests {
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty("schedules.businessHours", businessHoursCronExpression);
|
||||
placeholderDefinition.getPropertyValues().addPropertyValue("properties", properties);
|
||||
BeanDefinition targetDefinition = new RootBeanDefinition(
|
||||
ScheduledAnnotationBeanPostProcessorTests.PropertyPlaceholderTestBean.class);
|
||||
BeanDefinition targetDefinition = new RootBeanDefinition(PropertyPlaceholderWithCronTestBean.class);
|
||||
context.registerBeanDefinition("placeholder", placeholderDefinition);
|
||||
context.registerBeanDefinition("postProcessor", processorDefinition);
|
||||
context.registerBeanDefinition("target", targetDefinition);
|
||||
@@ -242,6 +239,70 @@ public class ScheduledAnnotationBeanPostProcessorTests {
|
||||
assertEquals(businessHoursCronExpression, task.getExpression());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void propertyPlaceholderWithFixedDelay() {
|
||||
StaticApplicationContext context = new StaticApplicationContext();
|
||||
BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class);
|
||||
BeanDefinition placeholderDefinition = new RootBeanDefinition(PropertyPlaceholderConfigurer.class);
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty("fixedDelay", "5000");
|
||||
properties.setProperty("initialDelay", "1000");
|
||||
placeholderDefinition.getPropertyValues().addPropertyValue("properties", properties);
|
||||
BeanDefinition targetDefinition = new RootBeanDefinition(PropertyPlaceholderWithFixedDelayTestBean.class);
|
||||
context.registerBeanDefinition("placeholder", placeholderDefinition);
|
||||
context.registerBeanDefinition("postProcessor", processorDefinition);
|
||||
context.registerBeanDefinition("target", targetDefinition);
|
||||
context.refresh();
|
||||
Object postProcessor = context.getBean("postProcessor");
|
||||
Object target = context.getBean("target");
|
||||
ScheduledTaskRegistrar registrar = (ScheduledTaskRegistrar)
|
||||
new DirectFieldAccessor(postProcessor).getPropertyValue("registrar");
|
||||
@SuppressWarnings("unchecked")
|
||||
List<IntervalTask> fixedDelayTasks = (List<IntervalTask>)
|
||||
new DirectFieldAccessor(registrar).getPropertyValue("fixedDelayTasks");
|
||||
assertEquals(1, fixedDelayTasks.size());
|
||||
IntervalTask task = fixedDelayTasks.get(0);
|
||||
ScheduledMethodRunnable runnable = (ScheduledMethodRunnable) task.getRunnable();
|
||||
Object targetObject = runnable.getTarget();
|
||||
Method targetMethod = runnable.getMethod();
|
||||
assertEquals(target, targetObject);
|
||||
assertEquals("fixedDelay", targetMethod.getName());
|
||||
assertEquals(1000L, task.getInitialDelay());
|
||||
assertEquals(5000L, task.getInterval());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void propertyPlaceholderWithFixedRate() {
|
||||
StaticApplicationContext context = new StaticApplicationContext();
|
||||
BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class);
|
||||
BeanDefinition placeholderDefinition = new RootBeanDefinition(PropertyPlaceholderConfigurer.class);
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty("fixedRate", "3000");
|
||||
properties.setProperty("initialDelay", "1000");
|
||||
placeholderDefinition.getPropertyValues().addPropertyValue("properties", properties);
|
||||
BeanDefinition targetDefinition = new RootBeanDefinition(PropertyPlaceholderWithFixedRateTestBean.class);
|
||||
context.registerBeanDefinition("placeholder", placeholderDefinition);
|
||||
context.registerBeanDefinition("postProcessor", processorDefinition);
|
||||
context.registerBeanDefinition("target", targetDefinition);
|
||||
context.refresh();
|
||||
Object postProcessor = context.getBean("postProcessor");
|
||||
Object target = context.getBean("target");
|
||||
ScheduledTaskRegistrar registrar = (ScheduledTaskRegistrar)
|
||||
new DirectFieldAccessor(postProcessor).getPropertyValue("registrar");
|
||||
@SuppressWarnings("unchecked")
|
||||
List<IntervalTask> fixedRateTasks = (List<IntervalTask>)
|
||||
new DirectFieldAccessor(registrar).getPropertyValue("fixedRateTasks");
|
||||
assertEquals(1, fixedRateTasks.size());
|
||||
IntervalTask task = fixedRateTasks.get(0);
|
||||
ScheduledMethodRunnable runnable = (ScheduledMethodRunnable) task.getRunnable();
|
||||
Object targetObject = runnable.getTarget();
|
||||
Method targetMethod = runnable.getMethod();
|
||||
assertEquals(target, targetObject);
|
||||
assertEquals("fixedRate", targetMethod.getName());
|
||||
assertEquals(1000L, task.getInitialDelay());
|
||||
assertEquals(3000L, task.getInterval());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void propertyPlaceholderForMetaAnnotation() {
|
||||
String businessHoursCronExpression = "0 0 9-17 * * MON-FRI";
|
||||
@@ -285,7 +346,7 @@ public class ScheduledAnnotationBeanPostProcessorTests {
|
||||
context.refresh();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test(expected = BeanCreationException.class)
|
||||
public void invalidCron() throws Throwable {
|
||||
StaticApplicationContext context = new StaticApplicationContext();
|
||||
BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class);
|
||||
@@ -293,12 +354,7 @@ public class ScheduledAnnotationBeanPostProcessorTests {
|
||||
ScheduledAnnotationBeanPostProcessorTests.InvalidCronTestBean.class);
|
||||
context.registerBeanDefinition("postProcessor", processorDefinition);
|
||||
context.registerBeanDefinition("target", targetDefinition);
|
||||
try {
|
||||
context.refresh();
|
||||
fail("expected exception");
|
||||
} catch (BeanCreationException ex) {
|
||||
throw ex.getRootCause();
|
||||
}
|
||||
context.refresh();
|
||||
}
|
||||
|
||||
@Test(expected = BeanCreationException.class)
|
||||
@@ -342,7 +398,7 @@ public class ScheduledAnnotationBeanPostProcessorTests {
|
||||
|
||||
static class FixedRateWithInitialDelayTestBean {
|
||||
|
||||
@Scheduled(initialDelay=1000, fixedRate=3000)
|
||||
@Scheduled(fixedRate=3000, initialDelay=1000)
|
||||
public void fixedRate() {
|
||||
}
|
||||
}
|
||||
@@ -395,13 +451,13 @@ public class ScheduledAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
|
||||
@Scheduled(fixedRate = 5000)
|
||||
@Scheduled(fixedRate=5000)
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
private static @interface EveryFiveSeconds {}
|
||||
|
||||
|
||||
@Scheduled(cron = "0 0 * * * ?")
|
||||
@Scheduled(cron="0 0 * * * ?")
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
private static @interface Hourly {}
|
||||
@@ -423,7 +479,7 @@ public class ScheduledAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
|
||||
static class PropertyPlaceholderTestBean {
|
||||
static class PropertyPlaceholderWithCronTestBean {
|
||||
|
||||
@Scheduled(cron = "${schedules.businessHours}")
|
||||
public void x() {
|
||||
@@ -431,7 +487,23 @@ public class ScheduledAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
|
||||
@Scheduled(cron = "${schedules.businessHours}")
|
||||
static class PropertyPlaceholderWithFixedDelayTestBean {
|
||||
|
||||
@Scheduled(fixedDelayString="${fixedDelay}", initialDelayString="${initialDelay}")
|
||||
public void fixedDelay() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class PropertyPlaceholderWithFixedRateTestBean {
|
||||
|
||||
@Scheduled(fixedRateString="${fixedRate}", initialDelayString="${initialDelay}")
|
||||
public void fixedRate() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Scheduled(cron="${schedules.businessHours}")
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
private static @interface BusinessHours {}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-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.
|
||||
@@ -487,7 +487,7 @@ public class CronTriggerTests {
|
||||
assertEquals(calendar.getTime(), date = trigger.nextExecutionTime(context2));
|
||||
}
|
||||
|
||||
@Test(expected=IllegalStateException.class)
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testNonExistentSpecificDate() throws Exception {
|
||||
// TODO: maybe try and detect this as a special case in parser?
|
||||
CronTrigger trigger = new CronTrigger("0 0 0 31 6 *", timeZone);
|
||||
|
||||
@@ -16,31 +16,22 @@
|
||||
|
||||
package org.springframework.scripting.groovy;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import groovy.lang.DelegatingMetaClass;
|
||||
import groovy.lang.GroovyObject;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
import groovy.lang.DelegatingMetaClass;
|
||||
import groovy.lang.GroovyObject;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.aop.target.dynamic.Refreshable;
|
||||
import org.springframework.tests.sample.beans.TestBean;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.UnsatisfiedDependencyException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.core.NestedRuntimeException;
|
||||
@@ -56,6 +47,12 @@ import org.springframework.scripting.support.ScriptFactoryPostProcessor;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.tests.Assume;
|
||||
import org.springframework.tests.TestGroup;
|
||||
import org.springframework.tests.sample.beans.TestBean;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.BDDMockito.*;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
@@ -350,7 +347,9 @@ public class GroovyScriptFactoryTests {
|
||||
|
||||
@Test
|
||||
public void testInlineScriptFromTag() throws Exception {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("groovy-with-xsd.xml", getClass());
|
||||
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("groovy-with-xsd.xml", getClass());
|
||||
BeanDefinition bd = ctx.getBeanFactory().getBeanDefinition("calculator");
|
||||
assertTrue(ObjectUtils.containsElement(bd.getDependsOn(), "messenger"));
|
||||
Calculator calculator = (Calculator) ctx.getBean("calculator");
|
||||
assertNotNull(calculator);
|
||||
assertFalse(calculator instanceof Refreshable);
|
||||
|
||||
Reference in New Issue
Block a user