diff --git a/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/PostConstruct.java b/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/PostConstruct.java new file mode 100644 index 00000000..118a0a45 --- /dev/null +++ b/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/PostConstruct.java @@ -0,0 +1,40 @@ +/******************************************************************************** + * Copyright (c) 2023-present Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * SPDX-License-Identifier: EPL-1.0 + ********************************************************************************/ +package org.eclipse.sisu; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * The PostConstruct annotation is used on a method that needs to be executed + * after dependency injection is done to perform any initialization. This + * method is invoked by Sisu before the class is put into service. + *

+ * This annotation is Sisu specific annotation, that has same semantics as + * {@link javax.annotation.PostConstruct} annotation has, and may be used + * interchangeably. + *

+ * To use annotation {@link org.eclipse.sisu.bean.LifecycleModule} needs to be + * installed. + * + * @since TBD + */ +@Target( value = { ElementType.METHOD } ) +@Retention( RetentionPolicy.RUNTIME ) +@Documented +public @interface PostConstruct { +} diff --git a/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/PreDestroy.java b/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/PreDestroy.java new file mode 100644 index 00000000..207c21ac --- /dev/null +++ b/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/PreDestroy.java @@ -0,0 +1,42 @@ +/******************************************************************************** + * Copyright (c) 2023-present Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * SPDX-License-Identifier: EPL-1.0 + ********************************************************************************/ +package org.eclipse.sisu; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * The PreDestroy annotation is used on methods as a callback notification to + * signal that the instance is in the process of being removed by the + * container. The method annotated with PreDestroy is typically used to + * release resources that it has been holding. + *

+ * This annotation is Sisu specific annotation, that has same semantics as + * {@link javax.annotation.PreDestroy} annotation has, and may be used + * interchangeably. + *

+ * To use annotation {@link org.eclipse.sisu.bean.LifecycleModule} needs to be + * installed. + * + * @since TBD + */ + +@Target( value = { ElementType.METHOD } ) +@Retention( RetentionPolicy.RUNTIME ) +@Documented +public @interface PreDestroy { +} diff --git a/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/bean/LifecycleBuilder.java b/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/bean/LifecycleBuilder.java index 1be49821..ece4ce9b 100644 --- a/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/bean/LifecycleBuilder.java +++ b/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/bean/LifecycleBuilder.java @@ -10,19 +10,37 @@ *******************************************************************************/ package org.eclipse.sisu.bean; +import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.List; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import org.eclipse.sisu.PostConstruct; +import org.eclipse.sisu.PreDestroy; /** * Builds {@link BeanLifecycle}s by searching class hierarchies for JSR250 annotations. */ final class LifecycleBuilder { + static + { + boolean hasJsr250Annotations; + try + { + hasJsr250Annotations = javax.annotation.PostConstruct.class.isAnnotation() + && javax.annotation.PreDestroy.class.isAnnotation(); + } + catch ( final LinkageError e ) + { + hasJsr250Annotations = false; + } + HAS_JSR250_ANNOTATIONS = hasJsr250Annotations; + } + + private static final boolean HAS_JSR250_ANNOTATIONS; + // ---------------------------------------------------------------------- // Implementation fields // ---------------------------------------------------------------------- @@ -83,7 +101,7 @@ private void addLifecycleMethods( final Class clazz ) { if ( isCandidateMethod( m ) ) { - if ( m.isAnnotationPresent( PostConstruct.class ) ) + if ( isAnnotationPresent( m, PostConstruct.class ) ) { foundStartMethod = true; if ( !isOverridden( m ) ) @@ -91,7 +109,7 @@ private void addLifecycleMethods( final Class clazz ) startMethods.add( m ); } } - else if ( m.isAnnotationPresent( PreDestroy.class ) ) + else if ( isAnnotationPresent( m, PreDestroy.class ) ) { foundStopMethod = true; if ( !isOverridden( m ) ) @@ -108,6 +126,23 @@ else if ( m.isAnnotationPresent( PreDestroy.class ) ) hierarchy.add( clazz ); } + private boolean isAnnotationPresent( final Method method, final Class annotationClass ) + { + boolean result = method.isAnnotationPresent( annotationClass ); + if ( !result && HAS_JSR250_ANNOTATIONS ) + { + if ( PostConstruct.class.equals( annotationClass ) ) + { + result = method.isAnnotationPresent( javax.annotation.PostConstruct.class ); + } + else if ( PreDestroy.class.equals( annotationClass ) ) + { + result = method.isAnnotationPresent( javax.annotation.PreDestroy.class ); + } + } + return result; + } + /** * Tests to see if the given method is overridden in the subclass hierarchy. * diff --git a/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/bean/LifecycleModule.java b/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/bean/LifecycleModule.java index 62735c51..e508bafb 100644 --- a/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/bean/LifecycleModule.java +++ b/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/bean/LifecycleModule.java @@ -10,9 +10,6 @@ *******************************************************************************/ package org.eclipse.sisu.bean; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; - import com.google.inject.Binder; import com.google.inject.Module; import com.google.inject.TypeLiteral; @@ -23,8 +20,10 @@ import com.google.inject.spi.TypeListener; /** - * Guice {@link Module} that provides JSR250 lifecycle management by following {@link PostConstruct} and - * {@link PreDestroy} annotations. The lifecycle can be controlled with the associated {@link BeanManager}. + * Guice {@link Module} that provides lifecycle management by following {@link org.eclipse.sisu.PostConstruct} + * and {@link org.eclipse.sisu.PreDestroy} annotations, or corresponding JSR250 {@link javax.annotation.PostConstruct} + * and {@link javax.annotation.PreDestroy} annotations. The lifecycle can be controlled with the associated + * {@link BeanManager}. */ public final class LifecycleModule implements Module