Skip to content

Commit 4af6b5a

Browse files
committed
Support for proxied class
1 parent 890dc52 commit 4af6b5a

File tree

6 files changed

+157
-4
lines changed

6 files changed

+157
-4
lines changed

shedlock-spring/src/main/java/net/javacrumbs/shedlock/spring/SpringLockConfigurationExtractor.java

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import net.javacrumbs.shedlock.core.SchedulerLock;
2121
import org.slf4j.Logger;
2222
import org.slf4j.LoggerFactory;
23+
import org.springframework.aop.support.AopUtils;
2324
import org.springframework.core.annotation.AnnotationUtils;
2425
import org.springframework.scheduling.support.ScheduledMethodRunnable;
2526

@@ -63,8 +64,7 @@ public SpringLockConfigurationExtractor(TemporalAmount defaultLockAtMostFor, Dur
6364
@Override
6465
public Optional<LockConfiguration> getLockConfiguration(Runnable task) {
6566
if (task instanceof ScheduledMethodRunnable) {
66-
Method method = ((ScheduledMethodRunnable) task).getMethod();
67-
SchedulerLock annotation = AnnotationUtils.findAnnotation(method, SchedulerLock.class);
67+
SchedulerLock annotation = findAnnotation((ScheduledMethodRunnable) task);
6868
if (shouldLock(annotation)) {
6969
Instant now = now();
7070
return Optional.of(new LockConfiguration(annotation.name(), now.plus(getLockAtMostFor(annotation)), now.plus(getLockAtLeastFor(annotation))));
@@ -75,6 +75,27 @@ public Optional<LockConfiguration> getLockConfiguration(Runnable task) {
7575
return Optional.empty();
7676
}
7777

78+
SchedulerLock findAnnotation(ScheduledMethodRunnable task) {
79+
Method method = task.getMethod();
80+
SchedulerLock annotation = AnnotationUtils.findAnnotation(method, SchedulerLock.class);
81+
if (annotation != null) {
82+
return annotation;
83+
} else {
84+
// Try to find annotation on proxied class
85+
Class<?> targetClass = AopUtils.getTargetClass(task.getTarget());
86+
if (targetClass != null && !task.getTarget().getClass().equals(targetClass)) {
87+
try {
88+
Method methodOnTarget = targetClass.getMethod(method.getName(), method.getParameterTypes());
89+
return AnnotationUtils.findAnnotation(methodOnTarget, SchedulerLock.class);
90+
} catch (NoSuchMethodException e) {
91+
return null;
92+
}
93+
} else {
94+
return null;
95+
}
96+
}
97+
}
98+
7899
TemporalAmount getLockAtMostFor(SchedulerLock annotation) {
79100
long valueFromAnnotation = annotation.lockAtMostFor();
80101
return valueFromAnnotation >= 0 ? Duration.of(valueFromAnnotation, MILLIS) : defaultLockAtMostFor;

shedlock-spring/src/test/java/net/javacrumbs/shedlock/spring/SpringLockConfigurationExtractorTest.java

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,11 @@
1717

1818
import net.javacrumbs.shedlock.core.LockConfiguration;
1919
import net.javacrumbs.shedlock.core.SchedulerLock;
20+
import net.javacrumbs.shedlock.spring.proxytest.BeanInterface;
21+
import net.javacrumbs.shedlock.spring.proxytest.DynamicProxyConfig;
22+
import net.javacrumbs.shedlock.spring.proxytest.SubclassProxyConfig;
2023
import org.junit.Test;
21-
import org.springframework.core.annotation.AnnotationUtils;
24+
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
2225
import org.springframework.scheduling.support.ScheduledMethodRunnable;
2326

2427
import java.time.Duration;
@@ -81,8 +84,25 @@ public void shouldGetPositiveGracePeriodFromAnnotation() throws NoSuchMethodExce
8184
assertThat(gracePeriod).isEqualTo(Duration.of(10, MILLIS));
8285
}
8386

87+
@Test
88+
public void shouldFindAnnotationOnDynamicProxy() throws NoSuchMethodException {
89+
doTestfindAnnotationOnProxy(DynamicProxyConfig.class);
90+
}
91+
92+
@Test
93+
public void shouldFindAnnotationOnSubclassProxy() throws NoSuchMethodException {
94+
doTestfindAnnotationOnProxy(SubclassProxyConfig.class);
95+
}
96+
97+
private void doTestfindAnnotationOnProxy(Class<?> config) throws NoSuchMethodException {
98+
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(config)) {
99+
BeanInterface bean = context.getBean(BeanInterface.class);
100+
assertThat(extractor.findAnnotation(new ScheduledMethodRunnable(bean, "method"))).isNotNull();
101+
}
102+
}
103+
84104
protected SchedulerLock getAnnotation(String method) throws NoSuchMethodException {
85-
return AnnotationUtils.findAnnotation(getClass().getMethod(method), SchedulerLock.class);
105+
return extractor.findAnnotation(new ScheduledMethodRunnable(this, method));
86106
}
87107

88108
public void methodWithoutAnnotation() {
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**
2+
* Copyright 2009-2016 the original author or authors.
3+
* <p>
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* <p>
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
* <p>
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package net.javacrumbs.shedlock.spring.proxytest;
17+
18+
import net.javacrumbs.shedlock.core.SchedulerLock;
19+
import org.springframework.scheduling.annotation.Async;
20+
21+
public class BeanImpl implements BeanInterface {
22+
23+
24+
@Override
25+
@SchedulerLock(name = "test")
26+
@Async // to generate proxy
27+
public void method() {
28+
29+
}
30+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
* Copyright 2009-2016 the original author or authors.
3+
* <p>
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* <p>
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
* <p>
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package net.javacrumbs.shedlock.spring.proxytest;
17+
18+
public interface BeanInterface {
19+
void method();
20+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* Copyright 2009-2016 the original author or authors.
3+
* <p>
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* <p>
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
* <p>
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package net.javacrumbs.shedlock.spring.proxytest;
17+
18+
import org.springframework.context.annotation.Bean;
19+
import org.springframework.context.annotation.Configuration;
20+
import org.springframework.scheduling.annotation.EnableAsync;
21+
22+
@Configuration
23+
@EnableAsync
24+
public class DynamicProxyConfig {
25+
26+
@Bean
27+
public BeanInterface bean() {
28+
return new BeanImpl();
29+
}
30+
31+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* Copyright 2009-2016 the original author or authors.
3+
* <p>
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* <p>
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
* <p>
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package net.javacrumbs.shedlock.spring.proxytest;
17+
18+
import org.springframework.context.annotation.Bean;
19+
import org.springframework.context.annotation.Configuration;
20+
import org.springframework.scheduling.annotation.EnableAsync;
21+
22+
@Configuration
23+
@EnableAsync(proxyTargetClass = true)
24+
public class SubclassProxyConfig {
25+
26+
@Bean
27+
public BeanInterface bean() {
28+
return new BeanImpl();
29+
}
30+
31+
}

0 commit comments

Comments
 (0)