Skip to content

Commit

Permalink
Change the way the bean instance is setup for decorators with field d…
Browse files Browse the repository at this point in the history
…elegate injection points
  • Loading branch information
stuartwdouglas committed Feb 16, 2012
1 parent a192b2b commit 75a9d96
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 156 deletions.
72 changes: 59 additions & 13 deletions impl/src/main/java/org/jboss/weld/bean/DecoratorImpl.java
Expand Up @@ -16,10 +16,32 @@
*/
package org.jboss.weld.bean;

import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.AnnotatedMethod;
import javax.enterprise.inject.spi.Decorator;
import javax.enterprise.inject.spi.InjectionTarget;
import javax.inject.Inject;

import javassist.util.proxy.ProxyObject;
import org.jboss.weld.bean.proxy.DecoratorProxy;
import org.jboss.weld.bean.proxy.DecoratorProxyFactory;
import org.jboss.weld.bean.proxy.ProxyMethodHandler;
import org.jboss.weld.bean.proxy.TargetBeanInstance;
import org.jboss.weld.bootstrap.BeanDeployerEnvironment;
import org.jboss.weld.bootstrap.api.ServiceRegistry;
import org.jboss.weld.exceptions.DefinitionException;
import org.jboss.weld.injection.FieldInjectionPoint;
import org.jboss.weld.injection.ForwardingInjectionTarget;
import org.jboss.weld.injection.MethodInjectionPoint;
import org.jboss.weld.injection.WeldInjectionPoint;
import org.jboss.weld.introspector.MethodSignature;
Expand All @@ -31,19 +53,6 @@
import org.jboss.weld.util.reflection.Formats;
import org.jboss.weld.util.reflection.Reflections;

import javax.enterprise.inject.spi.AnnotatedMethod;
import javax.enterprise.inject.spi.Decorator;
import javax.inject.Inject;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import static org.jboss.weld.logging.messages.BeanMessage.ABSTRACT_METHOD_MUST_MATCH_DECORATED_TYPE;
import static org.jboss.weld.logging.messages.BeanMessage.DECORATED_TYPE_PARAMETERIZED_DELEGATE_NOT;
import static org.jboss.weld.logging.messages.BeanMessage.DELEGATE_MUST_SUPPORT_EVERY_DECORATED_TYPE;
Expand Down Expand Up @@ -91,6 +100,7 @@ public static <T> DecoratorImpl<T> of(WeldClass<T> clazz, BeanManagerImpl beanMa
private WeldClass<?> annotatedDelegateItem;
private Map<MethodSignature, WeldMethod<?, ?>> decoratorMethods;
private WeldInjectionPoint<?, ?> delegateInjectionPoint;
private FieldInjectionPoint<?, ?> delegateFieldInjectionPoint;
private Set<Annotation> delegateBindings;
private Type delegateType;
private Set<Type> delegateTypes;
Expand Down Expand Up @@ -122,6 +132,9 @@ protected void initDecoratedTypes() {

protected void initDelegateInjectionPoint() {
this.delegateInjectionPoint = getDelegateInjectionPoints().iterator().next();
if(delegateInjectionPoint instanceof FieldInjectionPoint) {
this.delegateFieldInjectionPoint = (FieldInjectionPoint<?, ?>) delegateInjectionPoint;
}
}


Expand Down Expand Up @@ -197,6 +210,39 @@ private void checkAbstractMethods() {
}
}

@Override
public InjectionTarget<T> getInjectionTarget() {
final InjectionTarget<T> delegate = super.getInjectionTarget();
if(delegateFieldInjectionPoint != null) {
return new ForwardingInjectionTarget<T>() {
@Override
protected InjectionTarget<T> delegate() {
return delegate;
}

@Override
public void inject(final T instance, final CreationalContext<T> ctx) {
super.inject(instance, ctx);

if(delegateFieldInjectionPoint != null) {
if(instance instanceof DecoratorProxy) {

//this code is only applicable if the delegate is injected into a field
//as the proxy can't intercept the delegate when setting the field
//we need to now read the delegate from the field

//this is only needed for fields, as constructor and method injection are handed
//at injection time
final Object delegate = delegateFieldInjectionPoint.getWeldField().get(instance);
final ProxyMethodHandler handler = new ProxyMethodHandler(new TargetBeanInstance(delegate), DecoratorImpl.this);
((ProxyObject)instance).setHandler(handler);
}
}
}
};
}
return delegate;
}

public Set<Annotation> getDelegateQualifiers() {
return delegateBindings;
Expand Down
Expand Up @@ -16,6 +16,24 @@
*/
package org.jboss.weld.injection;

import java.io.ObjectInputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Type;
import java.util.Set;

import javax.decorator.Delegate;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.Instance;
import javax.enterprise.inject.spi.Annotated;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.Decorator;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.inject.Inject;

import edu.umd.cs.findbugs.annotations.SuppressWarnings;
import org.jboss.interceptor.util.proxy.TargetInstanceProxy;
import org.jboss.weld.bean.proxy.DecoratorProxy;
Expand All @@ -28,23 +46,6 @@
import org.jboss.weld.util.AnnotatedTypes;
import org.jboss.weld.util.reflection.Reflections;

import javax.decorator.Delegate;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.Instance;
import javax.enterprise.inject.spi.Annotated;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.Decorator;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.inject.Inject;
import java.io.ObjectInputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Type;
import java.util.Set;

import static org.jboss.weld.injection.Exceptions.rethrowException;
import static org.jboss.weld.logging.messages.BeanMessage.PROXY_REQUIRED;

Expand Down Expand Up @@ -94,6 +95,10 @@ public Bean<?> getBean() {
return declaringBean;
}

public WeldField<T, X> getWeldField() {
return field;
}

@Override
public Set<Annotation> getQualifiers() {
return delegate().getQualifiers();
Expand Down
@@ -0,0 +1,39 @@
package org.jboss.weld.injection;

import java.util.Set;

import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.enterprise.inject.spi.InjectionTarget;

/**
* @author Stuart Douglas
*/
public abstract class ForwardingInjectionTarget<T> implements InjectionTarget<T>{

protected abstract InjectionTarget<T> delegate();

public void inject(final T instance, final CreationalContext<T> ctx) {
delegate().inject(instance, ctx);
}

public void postConstruct(final T instance) {
delegate().postConstruct(instance);
}

public void preDestroy(final T instance) {
delegate().preDestroy(instance);
}

public T produce(final CreationalContext<T> ctx) {
return delegate().produce(ctx);
}

public void dispose(final T instance) {
delegate().dispose(instance);
}

public Set<InjectionPoint> getInjectionPoints() {
return delegate().getInjectionPoints();
}
}

This file was deleted.

Expand Up @@ -24,7 +24,6 @@
import javax.enterprise.inject.spi.Bean;

import javassist.util.proxy.ProxyObject;
import org.jboss.weld.bean.DecoratorImpl;
import org.jboss.weld.bean.proxy.BeanInstance;
import org.jboss.weld.bean.proxy.CombinedInterceptorAndDecoratorStackMethodHandler;
import org.jboss.weld.bean.proxy.ProxyFactory;
Expand Down Expand Up @@ -84,18 +83,6 @@ public T newInstance(final BeanManagerImpl manager, final CreationalContext<?> c
BeanInstance beanInstance = null;
if (decoratorDelegate != null) {
beanInstance = new TargetBeanInstance(decoratorDelegate);
} else if (bean instanceof DecoratorImpl) {
DecoratorImpl di = (DecoratorImpl) bean;
final WeldInjectionPoint ip = di.getDelegateInjectionPoint();
if (ip instanceof FieldInjectionPoint) {
beanInstance = new OnDemandBeanInstance(new FieldInstanceProvider<T>(ip, instance));
} else if (ip instanceof MethodInjectionPoint) {
beanInstance = new OnDemandBeanInstance(new MethodInstanceProvider<T>(ip, instance));
} else if (ip instanceof ParameterInjectionPoint) {
beanInstance = new OnDemandBeanInstance(new ParameterInstanceProvider(ip, manager, creationalContext));
} else {
throw new IllegalArgumentException("Invalid InjectionPoint: " + ip);
}
}
ProxyFactory.setBeanInstance(instance, beanInstance, bean);
} else {
Expand All @@ -105,56 +92,4 @@ public T newInstance(final BeanManagerImpl manager, final CreationalContext<?> c
}
return instance;
}

private static class FieldInstanceProvider<T> implements OnDemandBeanInstance.InstanceProvider {
private final WeldInjectionPoint ip;
private final T instance;

public FieldInstanceProvider(final WeldInjectionPoint ip, final T instance) {
this.ip = ip;
this.instance = instance;
}

public Object provideInstance() {
FieldInjectionPoint fip = (FieldInjectionPoint) ip;
return fip.delegate().get(instance);
}
}

private static class ParameterInstanceProvider implements OnDemandBeanInstance.InstanceProvider {
private final WeldInjectionPoint ip;
private final BeanManagerImpl manager;
private final CreationalContext<?> creationalContext;

public ParameterInstanceProvider(final WeldInjectionPoint ip, final BeanManagerImpl manager, final CreationalContext<?> creationalContext) {
this.ip = ip;
this.manager = manager;
this.creationalContext = creationalContext;
}

public Object provideInstance() {
ParameterInjectionPoint pip = (ParameterInjectionPoint) ip;
// special value handling?
return pip.getValueToInject(manager, creationalContext);
}
}

private static class MethodInstanceProvider<T> implements OnDemandBeanInstance.InstanceProvider {
private final WeldInjectionPoint ip;
private final T instance;

public MethodInstanceProvider(final WeldInjectionPoint ip, final T instance) {
this.ip = ip;
this.instance = instance;
}

public Object provideInstance() {
MethodInjectionPoint mip = (MethodInjectionPoint) ip;
try {
return mip.delegate().invokeOnInstance(instance);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}

0 comments on commit 75a9d96

Please sign in to comment.