diff --git a/org.springframework.context/src/main/java/org/springframework/context/expression/BeanFactoryResolver.java b/org.springframework.context/src/main/java/org/springframework/context/expression/BeanFactoryResolver.java new file mode 100644 index 00000000000..894a196f514 --- /dev/null +++ b/org.springframework.context/src/main/java/org/springframework/context/expression/BeanFactoryResolver.java @@ -0,0 +1,51 @@ +/* + * Copyright 2002-2010 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 org.springframework.context.expression; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.expression.AccessException; +import org.springframework.expression.BeanResolver; +import org.springframework.expression.EvaluationContext; +import org.springframework.util.Assert; + +/** + * EL bean resolver that operates against a Spring + * {@link org.springframework.beans.factory.BeanFactory}. + * + * @author Juergen Hoeller + * @since 3.0.4 + */ +public class BeanFactoryResolver implements BeanResolver { + + private final BeanFactory beanFactory; + + public BeanFactoryResolver(BeanFactory beanFactory) { + Assert.notNull(beanFactory, "BeanFactory must not be null"); + this.beanFactory = beanFactory; + } + + public Object resolve(EvaluationContext context, String beanName) throws AccessException { + try { + return this.beanFactory.getBean(beanName); + } + catch (BeansException ex) { + throw new AccessException("Could not resolve bean reference against BeanFactory", ex); + } + } + +} diff --git a/org.springframework.context/src/main/java/org/springframework/context/expression/StandardBeanExpressionResolver.java b/org.springframework.context/src/main/java/org/springframework/context/expression/StandardBeanExpressionResolver.java index cbcc1ab96fe..568874ebf74 100644 --- a/org.springframework.context/src/main/java/org/springframework/context/expression/StandardBeanExpressionResolver.java +++ b/org.springframework.context/src/main/java/org/springframework/context/expression/StandardBeanExpressionResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2010 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. @@ -126,6 +126,7 @@ public class StandardBeanExpressionResolver implements BeanExpressionResolver { sec.addPropertyAccessor(new BeanExpressionContextAccessor()); sec.addPropertyAccessor(new BeanFactoryAccessor()); sec.addPropertyAccessor(new MapAccessor()); + sec.setBeanResolver(new BeanFactoryResolver(evalContext.getBeanFactory())); sec.setTypeLocator(new StandardTypeLocator(evalContext.getBeanFactory().getBeanClassLoader())); ConversionService conversionService = evalContext.getBeanFactory().getConversionService(); if (conversionService != null) { diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/BeanResolver.java b/org.springframework.expression/src/main/java/org/springframework/expression/BeanResolver.java index 396ee2b3c08..22f164ecb7d 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/BeanResolver.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/BeanResolver.java @@ -17,20 +17,22 @@ package org.springframework.expression; /** - * A bean resolver can be registered with the evaluation context and will + * A bean resolver can be registered with the evaluation context + * and will kick in for @myBeanName still expressions. + * * @author Andy Clement * @since 3.0.3 */ public interface BeanResolver { /** - * Lookup the named bean and return it. + * Look up the named bean and return it. * @param context the current evaluation context - * @param beanname the name of the bean to lookup - * @return a object representing the bean + * @param beanName the name of the bean to lookup + * @return an object representing the bean * @throws AccessException if there is an unexpected problem resolving the named bean */ - Object resolve(EvaluationContext context, String beanname) throws AccessException; + Object resolve(EvaluationContext context, String beanName) throws AccessException; } \ No newline at end of file diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/EvaluationContext.java b/org.springframework.expression/src/main/java/org/springframework/expression/EvaluationContext.java index eed6c8c6b1d..27a83cab370 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/EvaluationContext.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/EvaluationContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2010 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. @@ -33,7 +33,8 @@ import java.util.List; public interface EvaluationContext { /** - * @return the default root context object against which unqualified properties/methods/etc should be resolved. This can be overridden when evaluating an expression. + * @return the default root context object against which unqualified properties/methods/etc + * should be resolved. This can be overridden when evaluating an expression. */ TypedValue getRootObject(); @@ -68,13 +69,13 @@ public interface EvaluationContext { TypeComparator getTypeComparator(); /** - * @return an operator overloader that may support mathematical operations between more than the standard set of - * types + * @return an operator overloader that may support mathematical operations + * between more than the standard set of types */ OperatorOverloader getOperatorOverloader(); /** - * @return a bean resolver that can lookup named beans + * @return a bean resolver that can look up beans by name */ BeanResolver getBeanResolver(); diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/tags/EvalTag.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/tags/EvalTag.java index 18ac1a90fd6..621dd44baef 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/tags/EvalTag.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/tags/EvalTag.java @@ -21,6 +21,7 @@ import javax.servlet.jsp.JspException; import javax.servlet.jsp.PageContext; import javax.servlet.jsp.el.VariableResolver; +import org.springframework.context.expression.BeanFactoryResolver; import org.springframework.core.convert.ConversionService; import org.springframework.expression.AccessException; import org.springframework.expression.EvaluationContext; @@ -59,12 +60,6 @@ public class EvalTag extends HtmlEscapingAwareTag { private boolean javaScriptEscape = false; - @Override - public void setPageContext(PageContext pageContext) { - super.setPageContext(pageContext); - this.evaluationContext = createEvaluationContext(pageContext); - } - /** * Set the expression to evaluate. */ @@ -105,6 +100,9 @@ public class EvalTag extends HtmlEscapingAwareTag { @Override public int doEndTag() throws JspException { + if (this.evaluationContext == null) { + this.evaluationContext = createEvaluationContext(pageContext); + } if (this.var == null) { try { String result = this.expression.getValue(this.evaluationContext, String.class); @@ -123,10 +121,10 @@ public class EvalTag extends HtmlEscapingAwareTag { return EVAL_PAGE; } - private EvaluationContext createEvaluationContext(PageContext pageContext) { StandardEvaluationContext context = new StandardEvaluationContext(); context.addPropertyAccessor(new JspPropertyAccessor(pageContext)); + context.setBeanResolver(new BeanFactoryResolver(getRequestContext().getWebApplicationContext())); ConversionService conversionService = getConversionService(pageContext); if (conversionService != null) { context.setTypeConverter(new StandardTypeConverter(conversionService)); diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/tags/EvalTagTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/tags/EvalTagTests.java index 0ae40d9b3c3..e281b14af9c 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/tags/EvalTagTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/tags/EvalTagTests.java @@ -19,11 +19,13 @@ package org.springframework.web.servlet.tags; import java.math.BigDecimal; import javax.servlet.jsp.tagext.Tag; +import org.springframework.context.support.GenericApplicationContext; import org.springframework.format.annotation.NumberFormat; import org.springframework.format.annotation.NumberFormat.Style; import org.springframework.format.support.FormattingConversionServiceFactoryBean; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.mock.web.MockPageContext; +import org.springframework.web.servlet.DispatcherServlet; /** * @author Keith Donald @@ -103,6 +105,19 @@ public class EvalTagTests extends AbstractTagTests { assertEquals("not the bean object", context.getAttribute("foo")); } + public void testAccessUsingBeanSyntax() throws Exception { + GenericApplicationContext wac = (GenericApplicationContext) + context.getRequest().getAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE); + wac.getDefaultListableBeanFactory().registerSingleton("bean2", context.getRequest().getAttribute("bean")); + tag.setExpression("@bean2.bean"); + tag.setVar("foo"); + int action = tag.doStartTag(); + assertEquals(Tag.EVAL_BODY_INCLUDE, action); + action = tag.doEndTag(); + assertEquals(Tag.EVAL_PAGE, action); + assertEquals("not the bean object", context.getAttribute("foo")); + } + public static class Bean {