Skip to content

Commit

Permalink
WELD-1345 Isolate InjectionTarget postConstruct() and preDestroy() lo…
Browse files Browse the repository at this point in the history
…gic into LifecycleCallbackInvokers
  • Loading branch information
jharting committed Mar 6, 2013
1 parent a40bade commit f6ed557
Show file tree
Hide file tree
Showing 5 changed files with 209 additions and 54 deletions.
Expand Up @@ -83,7 +83,7 @@ protected <T> void addDependentInstance(T instance, Contextual<T> contextual, We
ManagedBean<?> managedBean = (ManagedBean<?>) contextual;
if (managedBean.getProducer() instanceof AbstractInjectionTarget<?>) {
AbstractInjectionTarget<?> injectionTarget = (AbstractInjectionTarget<?>) managedBean.getProducer();
if (injectionTarget.getPreDestroyMethods().isEmpty() && !injectionTarget.hasInterceptors()) {
if (injectionTarget.getLifecycleCallbackInvoker().getPreDestroyMethods().isEmpty() && !injectionTarget.hasInterceptors()) {
// there is no @PreDestroy callback to call when destroying this dependent instance
// therefore, we do not need to keep the reference
return;
Expand Down
Expand Up @@ -18,18 +18,15 @@

import static org.jboss.weld.logging.messages.BeanMessage.FINAL_BEAN_CLASS_WITH_DECORATORS_NOT_ALLOWED;
import static org.jboss.weld.logging.messages.BeanMessage.FINAL_BEAN_CLASS_WITH_INTERCEPTORS_NOT_ALLOWED;
import static org.jboss.weld.logging.messages.BeanMessage.INVOCATION_ERROR;
import static org.jboss.weld.logging.messages.BeanMessage.NON_CONTAINER_DECORATOR;
import static org.jboss.weld.logging.messages.BeanMessage.SIMPLE_BEAN_AS_NON_STATIC_INNER_CLASS_NOT_ALLOWED;

import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.enterprise.context.Dependent;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.AnnotatedMethod;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.Decorator;
Expand All @@ -39,17 +36,14 @@

import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedMethod;
import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedType;
import org.jboss.weld.annotated.runtime.RuntimeAnnotatedMembers;
import org.jboss.weld.annotated.slim.SlimAnnotatedType;
import org.jboss.weld.bean.CustomDecoratorWrapper;
import org.jboss.weld.bean.DecoratorImpl;
import org.jboss.weld.exceptions.DefinitionException;
import org.jboss.weld.exceptions.DeploymentException;
import org.jboss.weld.exceptions.IllegalStateException;
import org.jboss.weld.exceptions.WeldException;
import org.jboss.weld.manager.BeanManagerImpl;
import org.jboss.weld.resources.ClassTransformer;
import org.jboss.weld.util.BeanMethods;
import org.jboss.weld.util.collections.WeldCollections;

/**
Expand All @@ -60,46 +54,29 @@ public abstract class AbstractInjectionTarget<T> extends AbstractProducer<T> imp

protected final BeanManagerImpl beanManager;
private final SlimAnnotatedType<T> type;
private final List<AnnotatedMethod<? super T>> postConstructMethods;
private final List<AnnotatedMethod<? super T>> preDestroyMethods;
private final Set<InjectionPoint> injectionPoints;
private final Bean<T> bean;

// Instantiation
private Instantiator<T> instantiator;
private final Injector<T> injector;
private final LifecycleCallbackInvoker<T> invoker;

public AbstractInjectionTarget(EnhancedAnnotatedType<T> type, Bean<T> bean, BeanManagerImpl beanManager) {
this.beanManager = beanManager;
this.type = type.slim();
Set<InjectionPoint> injectionPoints = new HashSet<InjectionPoint>();

this.bean = bean;
this.postConstructMethods = initPostConstructMethods(type);
this.preDestroyMethods = initPreDestroyMethods(type);

checkType(type);
this.injector = initInjector(type, bean, beanManager);
this.injector.registerInjectionPoints(injectionPoints);
this.instantiator = initInstantiator(type, bean, beanManager, injectionPoints);
this.injectionPoints = WeldCollections.immutableSet(injectionPoints);
checkDelegateInjectionPoints();
}

protected List<AnnotatedMethod<? super T>> initPostConstructMethods(EnhancedAnnotatedType<T> type) {
if (isInterceptor()) {
return Collections.emptyList();
} else {
return BeanMethods.getPostConstructMethods(type);
}
}

protected List<AnnotatedMethod<? super T>> initPreDestroyMethods(EnhancedAnnotatedType<T> type) {
if (isInterceptor()) {
return Collections.emptyList();
} else {
return BeanMethods.getPreDestroyMethods(type);
}
this.invoker = initInvoker(type);
}

protected void checkType(EnhancedAnnotatedType<T> type) {
Expand Down Expand Up @@ -161,29 +138,11 @@ public void inject(T instance, CreationalContext<T> ctx) {
}

public void postConstruct(T instance) {
for (AnnotatedMethod<? super T> method : postConstructMethods) {
if (method != null) {
try {
// note: RI supports injection into @PreDestroy
RuntimeAnnotatedMembers.invokeMethod(method, instance);
} catch (Exception e) {
throw new WeldException(INVOCATION_ERROR, e, method, instance);
}
}
}
invoker.postConstruct(instance, instantiator);
}

public void preDestroy(T instance) {
for (AnnotatedMethod<? super T> method : preDestroyMethods) {
if (method != null) {
try {
// note: RI supports injection into @PreDestroy
RuntimeAnnotatedMembers.invokeMethod(method, instance);
} catch (Exception e) {
throw new WeldException(INVOCATION_ERROR, e, method, instance);
}
}
}
invoker.preDestroy(instance, instantiator);
}

public void dispose(T instance) {
Expand Down Expand Up @@ -222,14 +181,6 @@ public boolean hasDecorators() {
return instantiator.hasDecoratorSupport();
}

public List<AnnotatedMethod<? super T>> getPostConstructMethods() {
return postConstructMethods;
}

public List<AnnotatedMethod<? super T>> getPreDestroyMethods() {
return preDestroyMethods;
}

protected void initializeAfterBeanDiscovery(EnhancedAnnotatedType<T> annotatedType) {
if (isInterceptionCandidate() && !beanManager.getInterceptorModelRegistry().containsKey(annotatedType.getJavaClass())) {
new InterceptionModelInitializer<T>(beanManager, annotatedType, getBean()).init();
Expand All @@ -248,6 +199,14 @@ protected Injector<T> initInjector(EnhancedAnnotatedType<T> type, Bean<T> bean,
return new DefaultInjector<T>(type, bean, beanManager);
}

protected LifecycleCallbackInvoker<T> initInvoker(EnhancedAnnotatedType<T> type) {
if (isInterceptor()) {
return NoopLifecycleCallbackInvoker.getInstance();
} else {
return new DefaultLifecycleCallbackInvoker<T>(type);
}
}

@Override
public AnnotatedType<T> getAnnotated() {
return type;
Expand All @@ -257,6 +216,10 @@ public Injector<T> getInjector() {
return injector;
}

public LifecycleCallbackInvoker<T> getLifecycleCallbackInvoker() {
return invoker;
}

@Override
public String toString() {
if (getBean() == null) {
Expand Down
@@ -0,0 +1,88 @@
/*
* JBoss, Home of Professional Open Source
* Copyright 2013, Red Hat, Inc., and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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.jboss.weld.injection.producer;

import static org.jboss.weld.logging.messages.BeanMessage.INVOCATION_ERROR;

import java.util.List;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.enterprise.inject.spi.AnnotatedMethod;

import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedType;
import org.jboss.weld.annotated.runtime.RuntimeAnnotatedMembers;
import org.jboss.weld.exceptions.WeldException;
import org.jboss.weld.interceptor.util.InterceptionUtils;
import org.jboss.weld.util.BeanMethods;

/**
* If the component is not intercepted this implementation takes care of invoking its lifecycle callback methods. If the
* component is interception, {@link PostConstruct} / {@link PreDestroy} invocation is delegated to the intercepting proxy.
*
* @author Jozef Hartinger
*
* @param <T>
*/
public class DefaultLifecycleCallbackInvoker<T> implements LifecycleCallbackInvoker<T> {

private final List<AnnotatedMethod<? super T>> postConstructMethods;
private final List<AnnotatedMethod<? super T>> preDestroyMethods;

public DefaultLifecycleCallbackInvoker(EnhancedAnnotatedType<T> type) {
this.postConstructMethods = BeanMethods.getPostConstructMethods(type);
this.preDestroyMethods = BeanMethods.getPreDestroyMethods(type);
}

@Override
public void postConstruct(T instance, Instantiator<T> instantiator) {
if (instantiator.hasInterceptorSupport()) {
InterceptionUtils.executePostConstruct(instance);
} else {
invokeMethods(postConstructMethods, instance);
}
}

@Override
public void preDestroy(T instance, Instantiator<T> instantiator) {
if (instantiator.hasInterceptorSupport()) {
InterceptionUtils.executePredestroy(instance);
} else {
invokeMethods(preDestroyMethods, instance);
}
}

protected void invokeMethods(List<AnnotatedMethod<? super T>> methods, T instance) {
for (AnnotatedMethod<? super T> method : methods) {
try {
RuntimeAnnotatedMembers.invokeMethod(method, instance);
} catch (Exception e) {
throw new WeldException(INVOCATION_ERROR, e, method, instance);
}
}
}

@Override
public List<AnnotatedMethod<? super T>> getPostConstructMethods() {
return postConstructMethods;
}

@Override
public List<AnnotatedMethod<? super T>> getPreDestroyMethods() {
return preDestroyMethods;
}
}
@@ -0,0 +1,42 @@
/*
* JBoss, Home of Professional Open Source
* Copyright 2013, Red Hat, Inc., and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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.jboss.weld.injection.producer;

import java.util.List;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.enterprise.inject.spi.AnnotatedMethod;

/**
* Implementations of this interface are capable of performing {@link PostConstruct} / {@link PreDestroy} lifecycle callback
* invocations.
*
* @author Jozef Hartinger
*
* @param <T>
*/
public interface LifecycleCallbackInvoker<T> {

void postConstruct(T instance, Instantiator<T> instantiator);

void preDestroy(T instance, Instantiator<T> instantiator);

List<AnnotatedMethod<? super T>> getPreDestroyMethods();

List<AnnotatedMethod<? super T>> getPostConstructMethods();
}
@@ -0,0 +1,62 @@
/*
* JBoss, Home of Professional Open Source
* Copyright 2013, Red Hat, Inc., and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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.jboss.weld.injection.producer;

import static org.jboss.weld.util.reflection.Reflections.cast;

import java.util.Collections;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.enterprise.inject.spi.AnnotatedMethod;
import javax.enterprise.inject.spi.Interceptor;

/**
* This implementation never invokes {@link PostConstruct} / {@link PreDestroy} callbacks. Useful for {@link Interceptor}
* instances for example.
*
* @author Jozef Hartinger
*
* @param <T>
*/
public class NoopLifecycleCallbackInvoker<T> implements LifecycleCallbackInvoker<T> {

public static final NoopLifecycleCallbackInvoker<Object> INSTANCE = new NoopLifecycleCallbackInvoker<Object>();

public static <T> NoopLifecycleCallbackInvoker<T> getInstance() {
return cast(INSTANCE);
}

@Override
public void postConstruct(T instance, Instantiator<T> instantiator) {
// noop
}

@Override
public void preDestroy(T instance, Instantiator<T> instantiator) {
// noop
}

public List<AnnotatedMethod<? super T>> getPreDestroyMethods() {
return Collections.emptyList();
}

public List<AnnotatedMethod<? super T>> getPostConstructMethods() {
return Collections.emptyList();
}
}

0 comments on commit f6ed557

Please sign in to comment.