Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Index: src/main/java/org/apache/camel/component/bean/BeanInfo.java
- ===================================================================
- --- src/main/java/org/apache/camel/component/bean/BeanInfo.java (revision 1442130)
- +++ src/main/java/org/apache/camel/component/bean/BeanInfo.java (working copy)
- @@ -20,16 +20,7 @@
- import java.lang.reflect.Method;
- import java.lang.reflect.Modifier;
- import java.lang.reflect.Proxy;
- -import java.util.ArrayList;
- -import java.util.Arrays;
- -import java.util.Collection;
- -import java.util.Collections;
- -import java.util.Comparator;
- -import java.util.HashMap;
- -import java.util.Iterator;
- -import java.util.List;
- -import java.util.Map;
- -
- +import java.util.*;
- import org.apache.camel.Attachments;
- import org.apache.camel.Body;
- import org.apache.camel.CamelContext;
- @@ -55,10 +46,10 @@
- /**
- * Represents the metadata about a bean type created via a combination of
- * introspection and annotations together with some useful sensible defaults
- - *
- - * @version
- */
- public class BeanInfo {
- + public static final String BEAN_INFO_CACHE_REGISTRY_KEY = "CamelBeanInfoCache";
- +
- private static final transient Logger LOG = LoggerFactory.getLogger(BeanInfo.class);
- private static final String CGLIB_CLASS_SEPARATOR = "$$";
- private static final List<Method> EXCLUDED_METHODS = new ArrayList<Method>();
- @@ -105,6 +96,22 @@
- this.type = type;
- this.strategy = strategy;
- + Map<CacheKey, BeanInfo> cache = (Map<CacheKey, BeanInfo>) camelContext.getRegistry().lookup(BEAN_INFO_CACHE_REGISTRY_KEY, Map.class);
- + CacheKey cacheKey = new CacheKey(type, explicitMethod, strategy);
- + if (cache != null) {
- + BeanInfo beanInfo = cache.get(cacheKey);
- + if (beanInfo != null) {
- + defaultMethod = beanInfo.defaultMethod;
- + operations = beanInfo.operations;
- + operationsWithBody = beanInfo.operationsWithBody;
- + operationsWithNoBody = beanInfo.operationsWithNoBody;
- + operationsWithCustomAnnotation = beanInfo.operationsWithCustomAnnotation;
- + operationsWithHandlerAnnotation = beanInfo.operationsWithHandlerAnnotation;
- + methodMap = beanInfo.methodMap;
- + return;
- + }
- + }
- +
- if (explicitMethod != null) {
- // must be a valid method
- if (!isValidMethod(type, explicitMethod)) {
- @@ -133,6 +140,10 @@
- operationsWithCustomAnnotation = Collections.unmodifiableList(operationsWithCustomAnnotation);
- operationsWithHandlerAnnotation = Collections.unmodifiableList(operationsWithHandlerAnnotation);
- methodMap = Collections.unmodifiableMap(methodMap);
- +
- + if (cache != null) {
- + cache.put(cacheKey, this);
- + }
- }
- public Class<?> getType() {
- @@ -155,15 +166,14 @@
- return answer;
- }
- - public MethodInvocation createInvocation(Object pojo, Exchange exchange)
- - throws AmbiguousMethodCallException, MethodNotFoundException {
- + public MethodInvocation createInvocation(Object pojo, Exchange exchange) throws AmbiguousMethodCallException, MethodNotFoundException {
- return createInvocation(pojo, exchange, null);
- }
- private MethodInvocation createInvocation(Object pojo, Exchange exchange, Method explicitMethod)
- - throws AmbiguousMethodCallException, MethodNotFoundException {
- + throws AmbiguousMethodCallException, MethodNotFoundException {
- MethodInfo methodInfo = null;
- -
- +
- // find the explicit method to invoke
- if (explicitMethod != null) {
- Iterator<List<MethodInfo>> it = operations.values().iterator();
- @@ -192,7 +202,8 @@
- if ("class".equals(name) || "getClass".equals(name)) {
- try {
- Method method = pojo.getClass().getMethod("getClass");
- - methodInfo = new MethodInfo(exchange.getContext(), pojo.getClass(), method, Collections.<ParameterInfo>emptyList(), Collections.<ParameterInfo>emptyList(), false, false);
- + methodInfo = new MethodInfo(exchange.getContext(), pojo.getClass(), method, Collections.<ParameterInfo>emptyList(),
- + Collections.<ParameterInfo>emptyList(), false, false);
- } catch (NoSuchMethodException e) {
- throw new MethodNotFoundException(exchange, pojo, "getClass");
- }
- @@ -252,12 +263,12 @@
- if (!Modifier.isPublic(clazz.getModifiers())) {
- LOG.trace("Preferring interface methods as class: {} is not public accessible", clazz);
- List<Method> interfaceMethods = getInterfaceMethods(clazz);
- -
- +
- // still keep non-accessible class methods to provide more specific Exception if method is non-accessible
- interfaceMethods.addAll(methods);
- methods = interfaceMethods;
- }
- -
- +
- for (Method method : methods) {
- boolean valid = isValidMethod(clazz, method);
- LOG.trace("Method: {} is valid: {}", method, valid);
- @@ -325,7 +336,6 @@
- return methodInfo;
- }
- -
- /**
- * Returns the {@link MethodInfo} for the given method if it exists or null
- * if there is no metadata available for the given method
- @@ -399,8 +409,7 @@
- }
- protected List<Annotation>[] collectParameterAnnotations(Class<?> c, Method m) {
- - @SuppressWarnings("unchecked")
- - List<Annotation>[] annotations = new List[m.getParameterTypes().length];
- + @SuppressWarnings("unchecked") List<Annotation>[] annotations = new List[m.getParameterTypes().length];
- for (int i = 0; i < annotations.length; i++) {
- annotations[i] = new ArrayList<Annotation>();
- }
- @@ -490,7 +499,7 @@
- possibleOperations.addAll(localOperationsWithCustomAnnotation);
- if (!possibleOperations.isEmpty()) {
- - // multiple possible operations so find the best suited if possible
- + // multiple possible operations so find the best suited if possible
- MethodInfo answer = chooseMethodWithMatchingBody(exchange, possibleOperations, localOperationsWithCustomAnnotation);
- if (answer == null) {
- throw new AmbiguousMethodCallException(exchange, possibleOperations);
- @@ -502,10 +511,9 @@
- // not possible to determine
- return null;
- }
- -
- - private MethodInfo chooseMethodWithMatchingBody(Exchange exchange, Collection<MethodInfo> operationList,
- - List<MethodInfo> operationsWithCustomAnnotation)
- - throws AmbiguousMethodCallException {
- +
- + private MethodInfo chooseMethodWithMatchingBody(Exchange exchange, Collection<MethodInfo> operationList, List<MethodInfo> operationsWithCustomAnnotation)
- + throws AmbiguousMethodCallException {
- // see if we can find a method whose body param type matches the message body
- Message in = exchange.getIn();
- Object body = in.getBody();
- @@ -546,10 +554,9 @@
- return null;
- }
- - private MethodInfo chooseBestPossibleMethodInfo(Exchange exchange, Collection<MethodInfo> operationList, Object body,
- - List<MethodInfo> possibles, List<MethodInfo> possiblesWithException,
- - List<MethodInfo> possibleWithCustomAnnotation)
- - throws AmbiguousMethodCallException {
- + private MethodInfo chooseBestPossibleMethodInfo(Exchange exchange, Collection<MethodInfo> operationList, Object body, List<MethodInfo> possibles,
- + List<MethodInfo> possiblesWithException, List<MethodInfo> possibleWithCustomAnnotation)
- + throws AmbiguousMethodCallException {
- Exception exception = ExpressionBuilder.exchangeExceptionExpression().evaluate(exchange, Exception.class);
- if (exception != null && possiblesWithException.size() == 1) {
- @@ -574,8 +581,7 @@
- Object value = exchange.getContext().getTypeConverter().tryConvertTo(methodInfo.getBodyParameterType(), exchange, body);
- if (value != null) {
- if (LOG.isTraceEnabled()) {
- - LOG.trace("Converted body from: {} to: {}",
- - body.getClass().getCanonicalName(), methodInfo.getBodyParameterType().getCanonicalName());
- + LOG.trace("Converted body from: {} to: {}", body.getClass().getCanonicalName(), methodInfo.getBodyParameterType().getCanonicalName());
- }
- matchCounter++;
- newBody = value;
- @@ -609,8 +615,8 @@
- /**
- * Validates whether the given method is a valid candidate for Camel Bean Binding.
- *
- - * @param clazz the class
- - * @param method the method
- + * @param clazz the class
- + * @param method the method
- * @return true if valid, false to skip the method
- */
- protected boolean isValidMethod(Class<?> clazz, Method method) {
- @@ -638,7 +644,7 @@
- /**
- * Does the given method info override an existing method registered before (from a subclass)
- *
- - * @param methodInfo the method to test
- + * @param methodInfo the method to test
- * @return the already registered method to use, null if not overriding any
- */
- private MethodInfo overridesExistingMethod(MethodInfo methodInfo) {
- @@ -656,8 +662,7 @@
- return null;
- }
- - private MethodInfo chooseMethodWithCustomAnnotations(Exchange exchange, Collection<MethodInfo> possibles)
- - throws AmbiguousMethodCallException {
- + private MethodInfo chooseMethodWithCustomAnnotations(Exchange exchange, Collection<MethodInfo> possibles) throws AmbiguousMethodCallException {
- // if we have only one method with custom annotations let's choose that
- MethodInfo chosen = null;
- for (MethodInfo possible : possibles) {
- @@ -682,8 +687,7 @@
- * insufficient annotations or not fitting with the default type
- * conventions.
- */
- - private Expression createParameterUnmarshalExpression(Class<?> clazz, Method method,
- - Class<?> parameterType, Annotation[] parameterAnnotation) {
- + private Expression createParameterUnmarshalExpression(Class<?> clazz, Method method, Class<?> parameterType, Annotation[] parameterAnnotation) {
- // look for a parameter annotation that converts into an expression
- for (Annotation annotation : parameterAnnotation) {
- @@ -696,17 +700,16 @@
- return strategy.getDefaultParameterTypeExpression(parameterType);
- }
- - private Expression createParameterUnmarshalExpressionForAnnotation(Class<?> clazz, Method method,
- - Class<?> parameterType, Annotation annotation) {
- + private Expression createParameterUnmarshalExpressionForAnnotation(Class<?> clazz, Method method, Class<?> parameterType, Annotation annotation) {
- if (annotation instanceof Attachments) {
- return ExpressionBuilder.attachmentsExpression();
- } else if (annotation instanceof Property) {
- - Property propertyAnnotation = (Property)annotation;
- + Property propertyAnnotation = (Property) annotation;
- return ExpressionBuilder.propertyExpression(propertyAnnotation.value());
- } else if (annotation instanceof Properties) {
- return ExpressionBuilder.propertiesExpression();
- } else if (annotation instanceof Header) {
- - Header headerAnnotation = (Header)annotation;
- + Header headerAnnotation = (Header) annotation;
- return ExpressionBuilder.headerExpression(headerAnnotation.value());
- } else if (annotation instanceof Headers) {
- return ExpressionBuilder.headersExpression();
- @@ -723,16 +726,15 @@
- AnnotationExpressionFactory expressionFactory = (AnnotationExpressionFactory) object;
- return expressionFactory.createExpression(camelContext, annotation, languageAnnotation, parameterType);
- } else {
- - LOG.warn("Ignoring bad annotation: " + languageAnnotation + "on method: " + method
- - + " which declares a factory: " + type.getName()
- - + " which does not implement " + AnnotationExpressionFactory.class.getName());
- + LOG.warn("Ignoring bad annotation: " + languageAnnotation + "on method: " + method + " which declares a factory: " + type.getName()
- + + " which does not implement " + AnnotationExpressionFactory.class.getName());
- }
- }
- }
- return null;
- }
- -
- +
- private static List<Method> getInterfaceMethods(Class<?> clazz) {
- final List<Method> answer = new ArrayList<Method>();
- for (Class<?> interfaceClazz : clazz.getInterfaces()) {
- @@ -822,7 +824,6 @@
- if (assignable != null && !assignable) {
- return false;
- }
- -
- } else {
- // there method has more parameters than was specified in the method name qualifiers
- return false;
- @@ -943,4 +944,47 @@
- return null;
- }
- + private static final class CacheKey {
- + private final Class<?> type;
- + private final Method explicitMethod;
- + private final Class<? extends ParameterMappingStrategy> strategyClass;
- +
- + public CacheKey(Class<?> type, Method explicitMethod, ParameterMappingStrategy strategy) {
- + this.type = type;
- + this.explicitMethod = explicitMethod;
- + this.strategyClass = strategy.getClass();
- + }
- +
- + @Override
- + public boolean equals(Object o) {
- + if (this == o) {
- + return true;
- + }
- + if (o == null || getClass() != o.getClass()) {
- + return false;
- + }
- +
- + CacheKey cacheKey = (CacheKey) o;
- +
- + if (explicitMethod != null ? !explicitMethod.equals(cacheKey.explicitMethod) : cacheKey.explicitMethod != null) {
- + return false;
- + }
- + if (!strategyClass.equals(cacheKey.strategyClass)) {
- + return false;
- + }
- + if (!type.equals(cacheKey.type)) {
- + return false;
- + }
- +
- + return true;
- + }
- +
- + @Override
- + public int hashCode() {
- + int result = type.hashCode();
- + result = 31 * result + (explicitMethod != null ? explicitMethod.hashCode() : 0);
- + result = 31 * result + strategyClass.hashCode();
- + return result;
- + }
- + }
- }
- Index: src/test/java/org/apache/camel/component/bean/CamelSimpleExpressionPerfTest.java
- ===================================================================
- --- src/test/java/org/apache/camel/component/bean/CamelSimpleExpressionPerfTest.java (revision 0)
- +++ src/test/java/org/apache/camel/component/bean/CamelSimpleExpressionPerfTest.java (working copy)
- @@ -0,0 +1,59 @@
- +package org.apache.camel.component.bean;
- +
- +import java.util.*;
- +import org.apache.camel.CamelContext;
- +import org.apache.camel.ProducerTemplate;
- +import org.apache.camel.builder.RouteBuilder;
- +import org.apache.camel.impl.DefaultCamelContext;
- +import org.apache.camel.impl.SimpleRegistry;
- +import org.apache.camel.model.RouteDefinition;
- +import org.apache.camel.spi.Registry;
- +
- +public class CamelSimpleExpressionPerfTest {
- + private static final int MESSAGE_LOOP_COUNT = 10000;
- + private static final int TEST_EXECUTION_COUNT = 5;
- +
- + public static void main(String[] args) throws Exception {
- + long bodyOnly = executePerformanceTest(new SimpleRegistry(), "${body}");
- + long bodyProperty = executePerformanceTest(new SimpleRegistry(), "${body[p]}");
- +
- + SimpleRegistry registry = new SimpleRegistry();
- + registry.put(BeanInfo.BEAN_INFO_CACHE_REGISTRY_KEY, new HashMap());
- + long bodyPropertyWithCache = executePerformanceTest(registry, "${body[p]}");
- +
- + System.out.printf("${body}: %dms%n", bodyOnly);
- + System.out.printf("${body[p]} : %dms%n", bodyProperty);
- + System.out.printf("${body[p]} with cache : %dms%n", bodyPropertyWithCache);
- + }
- +
- + private static long executePerformanceTest(Registry registry, final String simpleExpression) throws Exception {
- + CamelContext ctx = new DefaultCamelContext(registry);
- +
- + ctx.addRoutes(new RouteBuilder() {
- + @Override
- + public void configure() throws Exception {
- + from("direct:start").loop(MESSAGE_LOOP_COUNT).setHeader("test").simple(simpleExpression).to("mock:plop");
- + }
- + });
- +
- + ctx.start();
- +
- + Map<String, String> body = new HashMap<String, String>();
- + body.put("p", "q");
- +
- + ProducerTemplate template = ctx.createProducerTemplate();
- + // Initial one, it's a dry start, we don't care about this one.
- + template.sendBody("direct:start", body);
- +
- + // Measure the duration of the executions in nanoseconds
- + long totalNsDuration = 0;
- + for (int i = 0; i < TEST_EXECUTION_COUNT; i++) {
- + long tick = System.nanoTime();
- + template.sendBody("direct:start", body);
- + totalNsDuration += System.nanoTime() - tick;
- + }
- +
- + // Return the average duration in milliseconds
- + return totalNsDuration / TEST_EXECUTION_COUNT / 1000 / 1000;
- + }
- +}
Advertisement
Add Comment
Please, Sign In to add comment