class ExpressionRetryPolicy extends SimpleRetryPolicy implements BeanFactoryAware {

	private static final Log logger = LogFactory.getLog(ExpressionRetryPolicy.class);

	private static final TemplateParserContext PARSER_CONTEXT = new TemplateParserContext();

	private final Expression expression;

	private final StandardEvaluationContext evaluationContext = new StandardEvaluationContext();

	/**
	 * Construct an instance with the provided {@link Expression}.
	 * @param expression the expression
	 */
	public ExpressionRetryPolicy(Expression expression) {
		Assert.notNull(expression, "'expression' cannot be null");
		this.expression = expression;
	}

	/**
	 * Construct an instance with the provided expression.
	 * @param expressionString the expression.
	 */
	public ExpressionRetryPolicy(String expressionString) {
		Assert.notNull(expressionString, "'expressionString' cannot be null");
		this.expression = getExpression(expressionString);
	}

	/**
	 * Construct an instance with the provided {@link Expression}.
	 * @param maxAttempts the max attempts
	 * @param retryableExceptions the exceptions
	 * @param traverseCauses true to examine causes
	 * @param expression the expression
	 */
	public ExpressionRetryPolicy(int maxAttempts, Map<Class<? extends Throwable>, Boolean> retryableExceptions,
			boolean traverseCauses, Expression expression) {
		super(maxAttempts, retryableExceptions, traverseCauses);
		Assert.notNull(expression, "'expression' cannot be null");
		this.expression = expression;
	}

	/**
	 * Construct an instance with the provided expression.
	 * @param maxAttempts the max attempts
	 * @param retryableExceptions the exceptions
	 * @param traverseCauses true to examine causes
	 * @param expressionString the expression.
	 * @param defaultValue the default action
	 */
	public ExpressionRetryPolicy(int maxAttempts, Map<Class<? extends Throwable>, Boolean> retryableExceptions,
			boolean traverseCauses, String expressionString, boolean defaultValue) {
		super(maxAttempts, retryableExceptions, traverseCauses, defaultValue);
		Assert.notNull(expressionString, "'expressionString' cannot be null");
		this.expression = getExpression(expressionString);
	}

	@Override
	public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
		this.evaluationContext.setBeanResolver(new BeanFactoryResolver(beanFactory));
	}

	public ExpressionRetryPolicy withBeanFactory(BeanFactory beanFactory) {
		setBeanFactory(beanFactory);
		return this;
	}

	@Override
	public boolean canRetry(RetryContext context) {
		Throwable lastThrowable = context.getLastThrowable();
		if (lastThrowable == null) {
			return super.canRetry(context);
		}
		else {
			return super.canRetry(context)
					&& this.expression.getValue(this.evaluationContext, lastThrowable, Boolean.class);
		}
	}

	/**
	 * Get expression based on the expression string. At the moment supports both literal
	 * and template expressions. Template expressions are deprecated.
	 * @param expression the expression string
	 * @return literal expression or template expression
	 */
	private static Expression getExpression(String expression) {<FILL_FUNCTION_BODY>}

	/**
	 * Check if the expression is a template
	 * @param expression the expression string
	 * @return true if the expression string is a template
	 */
	public static boolean isTemplate(String expression) {
		return expression.contains(PARSER_CONTEXT.getExpressionPrefix())
				&& expression.contains(PARSER_CONTEXT.getExpressionSuffix());
	}

}

		if (isTemplate(expression)) {
			logger.warn("#{...} syntax is not required for this run-time expression "
					+ "and is deprecated in favor of a simple expression string");
			return new SpelExpressionParser().parseExpression(expression, PARSER_CONTEXT);
		}
		return new SpelExpressionParser().parseExpression(expression);
	
<methods>public void <init>() ,public void <init>(int) ,public void <init>(int, Map<Class<? extends java.lang.Throwable>,java.lang.Boolean>) ,public void <init>(int, Map<Class<? extends java.lang.Throwable>,java.lang.Boolean>, boolean) ,public void <init>(int, Map<Class<? extends java.lang.Throwable>,java.lang.Boolean>, boolean, boolean) ,public void <init>(int, org.springframework.classify.BinaryExceptionClassifier) ,public boolean canRetry(org.springframework.retry.RetryContext) ,public void close(org.springframework.retry.RetryContext) ,public int getMaxAttempts() ,public void maxAttemptsSupplier(Supplier<java.lang.Integer>) ,public org.springframework.retry.RetryContext open(org.springframework.retry.RetryContext) ,public void registerThrowable(org.springframework.retry.RetryContext, java.lang.Throwable) ,public void setMaxAttempts(int) ,public transient void setNotRecoverable(Class<? extends java.lang.Throwable>[]) ,public java.lang.String toString() <variables>public static final int DEFAULT_MAX_ATTEMPTS,private int maxAttempts,private Supplier<java.lang.Integer> maxAttemptsSupplier,private org.springframework.classify.BinaryExceptionClassifier recoverableClassifier,private org.springframework.classify.BinaryExceptionClassifier retryableClassifier