📄 valuebindingresolvinginstantiationstrategy.java
字号:
/* * Copyright 2002-2004 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 de.mindmatters.faces.spring.factory;import java.lang.reflect.Constructor;import java.lang.reflect.Method;import javax.faces.context.FacesContext;import net.sf.cglib.proxy.Callback;import net.sf.cglib.proxy.CallbackFilter;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;import net.sf.cglib.proxy.NoOp;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.springframework.beans.factory.BeanFactory;import org.springframework.beans.factory.support.LookupOverride;import org.springframework.beans.factory.support.MethodOverride;import org.springframework.beans.factory.support.MethodReplacer;import org.springframework.beans.factory.support.ReplaceOverride;import org.springframework.beans.factory.support.RootBeanDefinition;import org.springframework.beans.factory.support.SimpleInstantiationStrategy;import org.springframework.util.Assert;import de.mindmatters.faces.FacesUtils;/** * Default object instantiation strategy for use in ManagedBeanFactories which * resolves value bindings for replace- and lookup-methods. Uses CGLIB to * generate subclasses dynamically if methods need to be overridden by the * container to implement Method Injection. * * @author Andreas Kuhrwahl */public final class ValueBindingResolvingInstantiationStrategy extends SimpleInstantiationStrategy { /** * An inner class so we don't have a CGLIB dependency in core. */ private static class CglibSubclassCreator { /** * Index in the CGLIB callback array for passthrough behavior, in which * case the subclass won't override the original class. */ private static final int PASSTHROUGH = 0; /** * Index in the CGLIB callback array for a method that should be * overridden to provide method lookup. */ private static final int LOOKUP_OVERRIDE = 1; /** * Index in the CGLIB callback array for a method that should be * overridden using generic Methodreplacer functionality. */ private static final int METHOD_REPLACER = 2; /** * Class providing hashCode and equals methods required by CGLIB to * ensure that CGLIB doesn't generate a distinct class per bean. * Identity is based on class and bean name. * * @author Andreas Kuhrwahl */ private class CglibIdentitySupport { /** * Exposed for equals method to allow access to enclosing class * field. * * @return The encapsulated RootBeanDefinition */ private RootBeanDefinition getBeanDefinition() { return beanDefinition; } /** * Provided hashCode required by CGLIB to ensure that CGLIB doesn't * generate a distinct class per bean. * * @return a hash code value for this object. */ public final int hashCode() { return beanDefinition.hashCode(); } /** * Provided equals method required by CGLIB to ensure that CGLIB * doesn't generate a distinct class per bean. * * @param other * the reference object with which to compare. * @return <code>true</code> if this object is the same as the obj * argument; <code>false</code> otherwise. */ public final boolean equals(final Object other) { return (other.getClass() == getClass()) && ((CglibIdentitySupport) other).getBeanDefinition() == beanDefinition; } } /** * CGLIB object to filter method interception behavior. */ private class CallbackFilterImpl extends CglibIdentitySupport implements CallbackFilter { /** * {@inheritDoc} */ public int accept(final Method method) { final MethodOverride methodOverride = beanDefinition .getMethodOverrides().getOverride(method); if (logger.isDebugEnabled()) { logger.debug("Override for '" + method.getName() + "' is [" + methodOverride + "]"); } int returnCode; if (methodOverride == null) { returnCode = PASSTHROUGH; } else if (methodOverride instanceof LookupOverride) { returnCode = LOOKUP_OVERRIDE; } else if (methodOverride instanceof ReplaceOverride) { returnCode = METHOD_REPLACER; } else { throw new UnsupportedOperationException( "Unexpected MethodOverride subclass: " + methodOverride.getClass().getName()); } return returnCode; } } /** * CGLIB MethodInterceptor to override methods, replacing them with an * implementation that returns a bean looked up in the container or * resolved by a value binding. */ private class LookupOverrideMethodInterceptor extends CglibIdentitySupport implements MethodInterceptor { /** * {@inheritDoc} */ public Object intercept(final Object obj, final Method method, final Object[] args, final MethodProxy mp) throws Throwable { final LookupOverride lo = (LookupOverride) beanDefinition .getMethodOverrides().getOverride(method); final FacesContext context = getFacesContext(); Object bean = null; if (FacesUtils.isValueReference(lo.getBeanName())) { bean = context.getApplication().createValueBinding( lo.getBeanName()).getValue(context); } else { bean = owner.getBean(lo.getBeanName()); } return bean; } } /** * CGLIB MethodInterceptor to override methods, replacing them with a * call to a generic MethodReplacer (maybe resolved by a value binding). */ private class ReplaceOverrideMethodInterceptor extends CglibIdentitySupport implements MethodInterceptor { /** * {@inheritDoc} */ public Object intercept(final Object obj, final Method method, final Object[] args, final MethodProxy mp) throws Throwable { final ReplaceOverride ro = (ReplaceOverride) beanDefinition .getMethodOverrides().getOverride(method); MethodReplacer mr = null; final FacesContext context = getFacesContext(); if (FacesUtils.isValueReference(ro .getMethodReplacerBeanName())) { mr = (MethodReplacer) context.getApplication() .createValueBinding(ro.getMethodReplacerBeanName()) .getValue(context); } else { mr = (MethodReplacer) owner.getBean(ro .getMethodReplacerBeanName()); } return mr.reimplement(obj, method, args); } } /** For logging. */ private final Log logger = LogFactory.getLog(getClass()); /** The BeanDefinition subclasses are created for. */ private final RootBeanDefinition beanDefinition; /** The owning BeanFactory. */ private final BeanFactory owner; /** * Creates a subclass creator based on CGLib. * * @param beanDefinition * The BeanDefinition subclasses are created for. * @param owner * The owning BeanFactory. */ public CglibSubclassCreator(final RootBeanDefinition beanDefinition, final BeanFactory owner) { this.beanDefinition = beanDefinition; this.owner = owner; } /** * @return the current instance of the FacesContext */ private FacesContext getFacesContext() { final FacesContext context = FacesContext.getCurrentInstance(); Assert.notNull(context, "no faces-context"); return context; } /** * Create a new instance of a dynamically generated subclasses * implementing the required lookups. * * @param ctor * constructor to use. If this is <code>null</code>, use * the no-arg constructor (no parameterization, or Setter * Injection) * @param args * arguments to use for the constructor. Ignored if the ctor * parameter is <code>null</code>. * @return new instance of the dynamically generated class */ public Object instantiate(final Constructor ctor, final Object[] args) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.beanDefinition.getBeanClass()); enhancer.setCallbackFilter(new CallbackFilterImpl()); enhancer.setCallbacks(new Callback[] { NoOp.INSTANCE, new LookupOverrideMethodInterceptor(), new ReplaceOverrideMethodInterceptor() }); Object result = null; if (ctor == null) { result = enhancer.create(); } else { result = enhancer.create(ctor.getParameterTypes(), args); } return result; } } /** * {@inheritDoc} */ protected Object instantiateWithMethodInjection( final RootBeanDefinition beanDefinition, final String beanName, final BeanFactory owner) { return new CglibSubclassCreator(beanDefinition, owner).instantiate( null, null); } /** * {@inheritDoc} */ protected Object instantiateWithMethodInjection( final RootBeanDefinition beanDefinition, final String beanName, final BeanFactory owner, final Constructor ctor, final Object[] args) { return new CglibSubclassCreator(beanDefinition, owner).instantiate( ctor, args); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -