Yet more refactoring, trying to be able to pass DeserializationContext to ContextualDeserializer
diff --git a/src/main/java/com/fasterxml/jackson/databind/DeserializationConfig.java b/src/main/java/com/fasterxml/jackson/databind/DeserializationConfig.java
index 54050e6..b6b78d1 100644
--- a/src/main/java/com/fasterxml/jackson/databind/DeserializationConfig.java
+++ b/src/main/java/com/fasterxml/jackson/databind/DeserializationConfig.java
@@ -11,8 +11,6 @@
 import com.fasterxml.jackson.databind.cfg.MapperConfig;
 import com.fasterxml.jackson.databind.cfg.MapperConfigBase;
 import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler;
-import com.fasterxml.jackson.databind.deser.ValueInstantiator;
-import com.fasterxml.jackson.databind.introspect.Annotated;
 import com.fasterxml.jackson.databind.introspect.ClassIntrospector;
 import com.fasterxml.jackson.databind.introspect.NopAnnotationIntrospector;
 import com.fasterxml.jackson.databind.introspect.VisibilityChecker;
@@ -21,7 +19,6 @@
 import com.fasterxml.jackson.databind.node.JsonNodeFactory;
 import com.fasterxml.jackson.databind.type.ClassKey;
 import com.fasterxml.jackson.databind.type.TypeFactory;
-import com.fasterxml.jackson.databind.util.ClassUtil;
 import com.fasterxml.jackson.databind.util.LinkedNode;
 
 /**
@@ -667,55 +664,4 @@
     public <T extends BeanDescription> T introspectForCreation(JavaType type) {
         return (T) getClassIntrospector().forCreation(this, type, this);
     }
-    
-    /*
-    /**********************************************************
-    /* Extended API: handler instantiation
-    /**********************************************************
-     */
-
-    @SuppressWarnings("unchecked")
-    public JsonDeserializer<Object> deserializerInstance(Annotated annotated,
-            Class<?> deserClass)
-    {
-        HandlerInstantiator hi = getHandlerInstantiator();
-        if (hi != null) {
-            JsonDeserializer<?> deser = hi.deserializerInstance(this, annotated,
-                    (Class<JsonDeserializer<?>>)deserClass);
-            if (deser != null) {
-                return (JsonDeserializer<Object>) deser;
-            }
-        }
-        return (JsonDeserializer<Object>) ClassUtil.createInstance(deserClass, canOverrideAccessModifiers());
-    }
-
-    public KeyDeserializer keyDeserializerInstance(Annotated annotated,
-            Class<?> keyDeserClass)
-    {
-        HandlerInstantiator hi = getHandlerInstantiator();
-        if (hi != null) {
-            @SuppressWarnings("unchecked")
-            KeyDeserializer keyDeser = hi.keyDeserializerInstance(this, annotated,
-                    (Class<KeyDeserializer>)keyDeserClass);
-            if (keyDeser != null) {
-                return (KeyDeserializer) keyDeser;
-            }
-        }
-        return (KeyDeserializer) ClassUtil.createInstance(keyDeserClass, canOverrideAccessModifiers());
-    }
-
-    public ValueInstantiator valueInstantiatorInstance(Annotated annotated,
-            Class<?> instClass)
-    {
-        HandlerInstantiator hi = getHandlerInstantiator();
-        if (hi != null) {
-            @SuppressWarnings("unchecked")
-            ValueInstantiator inst = hi.valueInstantiatorInstance(this, annotated,
-                    (Class<ValueInstantiator>)instClass);
-            if (inst != null) {
-                return (ValueInstantiator) inst;
-            }
-        }
-        return (ValueInstantiator) ClassUtil.createInstance(instClass, canOverrideAccessModifiers());
-    }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/DeserializationContext.java b/src/main/java/com/fasterxml/jackson/databind/DeserializationContext.java
index 9370ef4..397bb8e 100644
--- a/src/main/java/com/fasterxml/jackson/databind/DeserializationContext.java
+++ b/src/main/java/com/fasterxml/jackson/databind/DeserializationContext.java
@@ -4,8 +4,10 @@
 import java.util.*;
 
 import com.fasterxml.jackson.core.*;
+
+import com.fasterxml.jackson.databind.cfg.MapperConfig;
 import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler;
-import com.fasterxml.jackson.databind.deser.DeserializerCache;
+import com.fasterxml.jackson.databind.introspect.Annotated;
 import com.fasterxml.jackson.databind.node.JsonNodeFactory;
 import com.fasterxml.jackson.databind.type.TypeFactory;
 import com.fasterxml.jackson.databind.util.ArrayBuilders;
@@ -45,12 +47,6 @@
      */
     public DeserializationConfig getConfig() { return _config; }
 
-    /**
-     * Returns provider that can be used for dynamically locating
-     * other deserializers during runtime.
-     */
-    public abstract DeserializerCache getDeserializerProvider();
-
     public final AnnotationIntrospector getAnnotationIntrospector() {
         return _config.getAnnotationIntrospector();
     }
@@ -66,6 +62,14 @@
         return (_featureFlags & feat.getMask()) != 0;
     }
 
+    public final boolean isEnabled(MapperConfig.Feature feat) {
+        return _config.isEnabled(feat);
+    }
+    
+    public final boolean canOverrideAccessModifiers() {
+        return _config.canOverrideAccessModifiers();
+    }
+
     /**
      * Convenience method for accessing the default Base64 encoding
      * used for decoding base64 encoded binary content.
@@ -134,6 +138,20 @@
     public abstract KeyDeserializer findKeyDeserializer(JavaType keyType,
             BeanProperty property)
         throws JsonMappingException;
+
+    /*
+    /**********************************************************
+    /* Extended API: handler instantiation
+    /**********************************************************
+     */
+
+    public abstract JsonDeserializer<Object> deserializerInstance(Annotated annotated,
+            BeanProperty property, Object deserDef)
+        throws JsonMappingException;
+
+    public abstract KeyDeserializer keyDeserializerInstance(Annotated annotated,
+            BeanProperty property, Object keyDeserClass)
+        throws JsonMappingException;
     
     /*
     /**********************************************************
diff --git a/src/main/java/com/fasterxml/jackson/databind/HandlerInstantiator.java b/src/main/java/com/fasterxml/jackson/databind/HandlerInstantiator.java
index b93fcb8..c83feaf 100644
--- a/src/main/java/com/fasterxml/jackson/databind/HandlerInstantiator.java
+++ b/src/main/java/com/fasterxml/jackson/databind/HandlerInstantiator.java
@@ -42,7 +42,7 @@
      * @return Deserializer instance to use
      */
     public abstract JsonDeserializer<?> deserializerInstance(DeserializationConfig config,
-            Annotated annotated, Class<? extends JsonDeserializer<?>> deserClass);
+            Annotated annotated, Class<?> deserClass);
 
     /**
      * Method called to get an instance of key deserializer of specified type.
@@ -56,7 +56,7 @@
      * @return Key deserializer instance to use
      */
     public abstract KeyDeserializer keyDeserializerInstance(DeserializationConfig config,
-            Annotated annotated, Class<? extends KeyDeserializer> keyDeserClass);
+            Annotated annotated, Class<?> keyDeserClass);
     
     /**
      * Method called to get an instance of serializer of specified type.
@@ -85,7 +85,7 @@
      * @return TypeResolverBuilder instance to use
      */
     public abstract TypeResolverBuilder<?> typeResolverBuilderInstance(MapperConfig<?> config,
-            Annotated annotated, Class<? extends TypeResolverBuilder<?>> builderClass);
+            Annotated annotated, Class<?> builderClass);
 
     /**
      * Method called to get an instance of TypeIdResolver of specified type.
@@ -100,13 +100,13 @@
      * @return TypeResolverBuilder instance to use
      */
     public abstract TypeIdResolver typeIdResolverInstance(MapperConfig<?> config,
-            Annotated annotated, Class<? extends TypeIdResolver> resolverClass);
+            Annotated annotated, Class<?> resolverClass);
 
     /**
      * Method called to construct an instance of ValueInstantiator of specified type.
      */
     public ValueInstantiator valueInstantiatorInstance(MapperConfig<?> config,
-            Annotated annotated, Class<? extends ValueInstantiator> resolverClass) {
+            Annotated annotated, Class<?> resolverClass) {
         return null;
     }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java b/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java
index 57f3e5b..9ebb8de 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java
@@ -225,7 +225,7 @@
      */
 
     @Override
-    public abstract ValueInstantiator findValueInstantiator(DeserializationConfig config,
+    public abstract ValueInstantiator findValueInstantiator(DeserializationContext ctxt,
             BeanDescription beanDesc)
         throws JsonMappingException;
 
@@ -234,7 +234,7 @@
             throws JsonMappingException;
     
     @Override
-    public JsonDeserializer<?> createArrayDeserializer(DeserializationConfig config,
+    public JsonDeserializer<?> createArrayDeserializer(DeserializationContext ctxt,
             ArrayType type, final BeanDescription beanDesc, BeanProperty property)
         throws JsonMappingException
     {
@@ -250,7 +250,8 @@
                  *   deserializers for all types (including primitive arrays) is useful
                  *   so let's allow this
                  */
-                JsonDeserializer<?> custom = _findCustomArrayDeserializer(type, config, property, null, null);
+                JsonDeserializer<?> custom = _findCustomArrayDeserializer(type,
+                        ctxt.getConfig(), property, null, null);
                 if (custom != null) {
                     return custom;
                 }
@@ -265,10 +266,11 @@
         TypeDeserializer elemTypeDeser = elemType.getTypeHandler();
         // but if not, may still be possible to find:
         if (elemTypeDeser == null) {
-            elemTypeDeser = findTypeDeserializer(config, elemType, property);
+            elemTypeDeser = findTypeDeserializer(ctxt.getConfig(), elemType, property);
         }
         // 23-Nov-2010, tatu: Custom array deserializer?
-        JsonDeserializer<?> custom = _findCustomArrayDeserializer(type, config, property, elemTypeDeser, contentDeser);
+        JsonDeserializer<?> custom = _findCustomArrayDeserializer(type,
+                ctxt.getConfig(), property, elemTypeDeser, contentDeser);
         if (custom != null) {
             return custom;
         }
@@ -276,7 +278,7 @@
     }
     
     @Override
-    public JsonDeserializer<?> createCollectionDeserializer(DeserializationConfig config,
+    public JsonDeserializer<?> createCollectionDeserializer(DeserializationContext ctxt,
             CollectionType type, BeanDescription beanDesc, BeanProperty property)
         throws JsonMappingException
     {
@@ -288,11 +290,12 @@
         TypeDeserializer contentTypeDeser = contentType.getTypeHandler();
         // but if not, may still be possible to find:
         if (contentTypeDeser == null) {
-            contentTypeDeser = findTypeDeserializer(config, contentType, property);
+            contentTypeDeser = findTypeDeserializer(ctxt.getConfig(), contentType, property);
         }
 
         // 23-Nov-2010, tatu: Custom deserializer?
-        JsonDeserializer<?> custom = _findCustomCollectionDeserializer(type, config, beanDesc, property,
+        JsonDeserializer<?> custom = _findCustomCollectionDeserializer(type,
+                ctxt.getConfig(), beanDesc, property,
                 contentTypeDeser, contentDeser);
         if (custom != null) {
             return custom;
@@ -322,11 +325,11 @@
                 throw new IllegalArgumentException("Can not find a deserializer for non-concrete Collection type "+type);
             }
             collectionClass = fallback;
-            type = (CollectionType) config.constructSpecializedType(type, collectionClass);
+            type = (CollectionType) ctxt.getConfig().constructSpecializedType(type, collectionClass);
             // But if so, also need to re-check creators...
-            beanDesc = config.introspectForCreation(type);
+            beanDesc = ctxt.getConfig().introspectForCreation(type);
         }
-        ValueInstantiator inst = findValueInstantiator(config, beanDesc);
+        ValueInstantiator inst = findValueInstantiator(ctxt, beanDesc);
         // 13-Dec-2010, tatu: Can use more optimal deserializer if content type is String, so:
         if (contentType.getRawClass() == String.class) {
             // no value type deserializer because Strings are one of natural/native types:
@@ -337,7 +340,7 @@
 
     // Copied almost verbatim from "createCollectionDeserializer" -- should try to share more code
     @Override
-    public JsonDeserializer<?> createCollectionLikeDeserializer(DeserializationConfig config,
+    public JsonDeserializer<?> createCollectionLikeDeserializer(DeserializationContext ctxt,
             CollectionLikeType type, final BeanDescription beanDesc, BeanProperty property)
         throws JsonMappingException
     {
@@ -349,17 +352,18 @@
         TypeDeserializer contentTypeDeser = contentType.getTypeHandler();
         // but if not, may still be possible to find:
         if (contentTypeDeser == null) {
-            contentTypeDeser = findTypeDeserializer(config, contentType, property);
+            contentTypeDeser = findTypeDeserializer(ctxt.getConfig(), contentType, property);
         }
-        return _findCustomCollectionLikeDeserializer(type, config, beanDesc, property,
+        return _findCustomCollectionLikeDeserializer(type, ctxt.getConfig(), beanDesc, property,
                 contentTypeDeser, contentDeser);
     }
     
     @Override
-    public JsonDeserializer<?> createMapDeserializer(DeserializationConfig config,
+    public JsonDeserializer<?> createMapDeserializer(DeserializationContext ctxt,
             MapType type, BeanDescription beanDesc, BeanProperty property)
         throws JsonMappingException
     {
+        final DeserializationConfig config = ctxt.getConfig();
         JavaType keyType = type.getKeyType();
         JavaType contentType = type.getContentType();
         
@@ -415,7 +419,7 @@
             // But if so, also need to re-check creators...
             beanDesc = config.introspectForCreation(type);
         }
-        ValueInstantiator inst = findValueInstantiator(config, beanDesc);
+        ValueInstantiator inst = findValueInstantiator(ctxt, beanDesc);
         MapDeserializer md = new MapDeserializer(type, property, inst, keyDes, contentDeser, contentTypeDeser);
         md.setIgnorableProperties(config.getAnnotationIntrospector().findPropertiesToIgnore(beanDesc.getClassInfo()));
         return md;
@@ -423,7 +427,7 @@
 
     // Copied almost verbatim from "createMapDeserializer" -- should try to share more code
     @Override
-    public JsonDeserializer<?> createMapLikeDeserializer(DeserializationConfig config,
+    public JsonDeserializer<?> createMapLikeDeserializer(DeserializationContext ctxt,
             MapLikeType type, final BeanDescription beanDesc, BeanProperty property)
         throws JsonMappingException
     {
@@ -445,36 +449,37 @@
         TypeDeserializer contentTypeDeser = contentType.getTypeHandler();
         // but if not, may still be possible to find:
         if (contentTypeDeser == null) {
-            contentTypeDeser = findTypeDeserializer(config, contentType, property);
+            contentTypeDeser = findTypeDeserializer(ctxt.getConfig(), contentType, property);
         }
-        return _findCustomMapLikeDeserializer(type, config, beanDesc, property,
-                keyDes, contentTypeDeser, contentDeser);
+        return _findCustomMapLikeDeserializer(type, ctxt.getConfig(),
+                beanDesc, property, keyDes, contentTypeDeser, contentDeser);
     }
 
     /**
      * Factory method for constructing serializers of {@link Enum} types.
      */
     @Override
-    public JsonDeserializer<?> createEnumDeserializer(DeserializationConfig config,
+    public JsonDeserializer<?> createEnumDeserializer(DeserializationContext ctxt,
             JavaType type, BeanDescription beanDesc, BeanProperty property)
         throws JsonMappingException
     {
         Class<?> enumClass = type.getRawClass();
         // 23-Nov-2010, tatu: Custom deserializer?
-        JsonDeserializer<?> custom = _findCustomEnumDeserializer(enumClass, config, beanDesc, property);
+        JsonDeserializer<?> custom = _findCustomEnumDeserializer(enumClass,
+                ctxt.getConfig(), beanDesc, property);
         if (custom != null) {
             return custom;
         }
 
         // [JACKSON-193] May have @JsonCreator for static factory method:
         for (AnnotatedMethod factory : beanDesc.getFactoryMethods()) {
-            if (config.getAnnotationIntrospector().hasCreatorAnnotation(factory)) {
+            if (ctxt.getAnnotationIntrospector().hasCreatorAnnotation(factory)) {
                 int argCount = factory.getParameterCount();
                 if (argCount == 1) {
                     Class<?> returnType = factory.getRawType();
                     // usually should be class, but may be just plain Enum<?> (for Enum.valueOf()?)
                     if (returnType.isAssignableFrom(enumClass)) {
-                        return EnumDeserializer.deserializerForCreator(config, enumClass, factory);
+                        return EnumDeserializer.deserializerForCreator(ctxt.getConfig(), enumClass, factory);
                     }
                 }
                 throw new IllegalArgumentException("Unsuitable method ("+factory+") decorated with @JsonCreator (for Enum type "
@@ -482,7 +487,7 @@
             }
         }
         // [JACKSON-749] Also, need to consider @JsonValue, if one found
-        return new EnumDeserializer(constructEnumResolver(enumClass, config, beanDesc.findJsonValueMethod()));
+        return new EnumDeserializer(constructEnumResolver(enumClass, ctxt.getConfig(), beanDesc.findJsonValueMethod()));
     }
 
     @Override
@@ -574,10 +579,11 @@
     }
 
     @Override
-    public KeyDeserializer createKeyDeserializer(DeserializationConfig config, JavaType type,
-            BeanProperty property)
+    public KeyDeserializer createKeyDeserializer(DeserializationContext ctxt,
+            JavaType type, BeanProperty property)
         throws JsonMappingException
     {
+        final DeserializationConfig config = ctxt.getConfig();
         if (_factoryConfig.hasKeyDeserializers()) {
             BeanDescription beanDesc = config.introspectClassAnnotations(type.getRawClass());
             for (KeyDeserializers d  : _factoryConfig.keyDeserializers()) {
@@ -588,31 +594,31 @@
             }
         }
         // and if none found, standard ones:
-        // No serializer needed if it's plain old String, or Object/untyped
         Class<?> raw = type.getRawClass();
         if (raw == String.class || raw == Object.class) {
             return StdKeyDeserializers.constructStringKeyDeserializer(config, type);
         }
-        // Most other keys are of limited number of static types
+        // Most other keys are for limited number of static types
         KeyDeserializer kdes = _keyDeserializers.get(type);
         if (kdes != null) {
             return kdes;
         }
         // And then other one-offs; first, Enum:
         if (type.isEnumType()) {
-            return _createEnumKeyDeserializer(config, type, property);
+            return _createEnumKeyDeserializer(ctxt, type, property);
         }
         // One more thing: can we find ctor(String) or valueOf(String)?
         kdes = StdKeyDeserializers.findStringBasedKeyDeserializer(config, type);
         return kdes;
     }
 
-    private KeyDeserializer _createEnumKeyDeserializer(DeserializationConfig config,
+    private KeyDeserializer _createEnumKeyDeserializer(DeserializationContext ctxt,
             JavaType type, BeanProperty property)
         throws JsonMappingException
     {
+        final DeserializationConfig config = ctxt.getConfig();
         BeanDescription beanDesc = config.introspect(type);
-        JsonDeserializer<?> des = findDeserializerFromAnnotation(config, beanDesc.getClassInfo(), property);
+        JsonDeserializer<?> des = findDeserializerFromAnnotation(ctxt, beanDesc.getClassInfo(), property);
         if (des != null) {
             return StdKeyDeserializers.constructDelegatingKeyDeserializer(config, type, des);
         }
@@ -722,39 +728,15 @@
      * has annotation that tells which class to use for deserialization.
      * Returns null if no such annotation found.
      */
-    @SuppressWarnings("unchecked")
-    protected JsonDeserializer<Object> findDeserializerFromAnnotation(DeserializationConfig config,
+    protected JsonDeserializer<Object> findDeserializerFromAnnotation(DeserializationContext ctxt,
             Annotated ann, BeanProperty property)
         throws JsonMappingException
     {
-        Object deserDef = config.getAnnotationIntrospector().findDeserializer(ann);
+        Object deserDef = ctxt.getAnnotationIntrospector().findDeserializer(ann);
         if (deserDef == null) {
             return null;
         }
-        if (deserDef instanceof JsonDeserializer) {
-            JsonDeserializer<Object> deser = (JsonDeserializer<Object>) deserDef;
-            // related to [JACKSON-569], need contextualization:
-            if (deser instanceof ContextualDeserializer<?>) {
-                deser = (JsonDeserializer<Object>)((ContextualDeserializer<?>) deser).createContextual(config, property);
-            }
-            return deser;
-        }
-        /* Alas, there's no way to force return type of "either class
-         * X or Y" -- need to throw an exception after the fact
-         */
-        if (!(deserDef instanceof Class)) {
-            throw new IllegalStateException("AnnotationIntrospector returned deserializer definition of type "+deserDef.getClass().getName()+"; expected type JsonDeserializer or Class<JsonDeserializer> instead");
-        }
-        Class<? extends JsonDeserializer<?>> deserClass = (Class<? extends JsonDeserializer<?>>) deserDef;
-        if (!JsonDeserializer.class.isAssignableFrom(deserClass)) {
-            throw new IllegalStateException("AnnotationIntrospector returned Class "+deserClass.getName()+"; expected Class<JsonDeserializer>");
-        }
-        JsonDeserializer<Object> deser = config.deserializerInstance(ann, deserClass);
-        // related to [JACKSON-569], need contextualization:
-        if (deser instanceof ContextualDeserializer<?>) {
-            deser = (JsonDeserializer<Object>)((ContextualDeserializer<?>) deser).createContextual(config, property);
-        }
-        return deser;
+        return ctxt.deserializerInstance(ann, property, deserDef);
     }
 
     /**
@@ -764,48 +746,28 @@
      * using generic type passed as type reference), which is
      * needed in some cases.
      */
-    protected JavaType resolveType(DeserializationConfig config,
+    protected JavaType resolveType(DeserializationContext ctxt,
             BeanDescription beanDesc, JavaType type, AnnotatedMember member,
             BeanProperty property)                    
         throws JsonMappingException
     {
         // [JACKSON-154]: Also need to handle keyUsing, contentUsing
         if (type.isContainerType()) {
-            AnnotationIntrospector intr = config.getAnnotationIntrospector();
+            AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
             JavaType keyType = type.getKeyType();
             if (keyType != null) {
                 Object kdDef = intr.findKeyDeserializer(member);
-                if (kdDef != null) {
-                    KeyDeserializer kd = null;
-                    if (kdDef instanceof KeyDeserializer) {
-                        kd = (KeyDeserializer) kdDef;
-                    } else {
-                        Class<?> kdClass = _verifyAsClass(kdDef, "findKeyDeserializer", KeyDeserializer.None.class);
-                        if (kdClass != null) {
-                            kd = config.keyDeserializerInstance(member, kdClass);
-                        }
-                    }
-                    if (kd != null) {
-                        type = ((MapLikeType) type).withKeyValueHandler(kd);
-                        keyType = type.getKeyType(); // just in case it's used below
-                    }
+                KeyDeserializer kd = ctxt.keyDeserializerInstance(member, property, kdDef);
+                if (kd != null) {
+                    type = ((MapLikeType) type).withKeyValueHandler(kd);
+                    keyType = type.getKeyType(); // just in case it's used below
                 }
             }
             // and all container types have content types...
             Object cdDef = intr.findContentDeserializer(member);
-            if (cdDef != null) {
-                JsonDeserializer<?> cd = null;
-                if (cdDef instanceof JsonDeserializer<?>) {
-                    cd = (JsonDeserializer<?>) cdDef;
-                } else {
-                    Class<?> cdClass = _verifyAsClass(cdDef, "findContentDeserializer", JsonDeserializer.None.class);
-                    if (cdClass != null) {
-                        cd = config.deserializerInstance(member, cdClass);
-                    }
-                }
-                if (cd != null) {
-                    type = type.withContentValueHandler(cd);
-                }
+            JsonDeserializer<?> cd = ctxt.deserializerInstance(member, property, cdDef);
+            if (cd != null) {
+                type = type.withContentValueHandler(cd);
             }
             /* 04-Feb-2010, tatu: Need to figure out JAXB annotations that indicate type
              *    information to use for polymorphic members; and specifically types for
@@ -813,8 +775,8 @@
              *    ... but only applies to members (fields, methods), not classes
              */
             if (member instanceof AnnotatedMember) {
-            	TypeDeserializer contentTypeDeser = findPropertyContentTypeDeserializer(config, type,
-            	       (AnnotatedMember) member, property);            	
+            	TypeDeserializer contentTypeDeser = findPropertyContentTypeDeserializer(
+            	        ctxt.getConfig(), type, (AnnotatedMember) member, property);            	
             	if (contentTypeDeser != null) {
             	    type = type.withContentTypeHandler(contentTypeDeser);
             	}
@@ -823,10 +785,11 @@
     	TypeDeserializer valueTypeDeser;
 
         if (member instanceof AnnotatedMember) { // JAXB allows per-property annotations
-            valueTypeDeser = findPropertyTypeDeserializer(config, type, (AnnotatedMember) member, property);
+            valueTypeDeser = findPropertyTypeDeserializer(ctxt.getConfig(),
+                    type, (AnnotatedMember) member, property);
         } else { // classes just have Jackson annotations
             // probably only occurs if 'property' is null anyway
-            valueTypeDeser = findTypeDeserializer(config, type, null);
+            valueTypeDeser = findTypeDeserializer(ctxt.getConfig(), type, null);
         }
     	if (valueTypeDeser != null) {
             type = type.withTypeHandler(valueTypeDeser);
@@ -834,6 +797,44 @@
     	return type;
     }
     
+    public ValueInstantiator valueInstantiatorInstance(DeserializationConfig config,
+            Annotated annotated, Object instDef)
+        throws JsonMappingException
+    {
+        if (instDef == null) {
+            return null;
+        }
+
+        ValueInstantiator inst;
+        
+        if (instDef instanceof ValueInstantiator) {
+            inst = (ValueInstantiator) instDef;
+        } else {
+            if (!(instDef instanceof Class)) {
+                throw new IllegalStateException("AnnotationIntrospector returned key deserializer definition of type "
+                        +instDef.getClass().getName()
+                        +"; expected type KeyDeserializer or Class<KeyDeserializer> instead");
+            }
+            Class<?> instClass = (Class<?>)instDef;
+            if (instClass == NoClass.class) {
+                return null;
+            }
+            if (!ValueInstantiator.class.isAssignableFrom(instClass)) {
+                throw new IllegalStateException("AnnotationIntrospector returned Class "+instClass.getName()
+                        +"; expected Class<ValueInstantiator>");
+            }
+            HandlerInstantiator hi = config.getHandlerInstantiator();
+            if (hi != null) {
+                inst = hi.valueInstantiatorInstance(config, annotated, instClass);
+            } else {
+                inst = (ValueInstantiator) ClassUtil.createInstance(instClass,
+                        config.canOverrideAccessModifiers());
+            }
+        }
+        // not resolvable or contextual, just return:
+        return inst;
+    }
+    
     protected EnumResolver<?> constructEnumResolver(Class<?> enumClass, DeserializationConfig config,
             AnnotatedMethod jsonValueMethod)
     {
@@ -859,19 +860,4 @@
         BeanDescription beanDesc = config.introspect(enumType);
         return beanDesc.findJsonValueMethod();
     }
-
-    protected Class<?> _verifyAsClass(Object src, String methodName, Class<?> noneClass)
-    {
-        if (src == null) {
-            return null;
-        }
-        if (!(src instanceof Class)) {
-            throw new IllegalStateException("AnnotationIntrospector."+methodName+"() returned value of type "+src.getClass().getName()+": expected type JsonSerializer or Class<JsonSerializer> instead");
-        }
-        Class<?> cls = (Class<?>) src;
-        if (cls == noneClass || cls == NoClass.class) {
-            return null;
-        }
-        return cls;
-    }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializer.java
index b21704c..bd1b405 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializer.java
@@ -1367,22 +1367,19 @@
             return subDeser;
         }
         // If not, maybe we can locate one. First, need provider
-        DeserializerCache deserProv = ctxt.getDeserializerProvider();
-        if (deserProv != null) {
-            JavaType type = ctxt.constructType(bean.getClass());
-            /* 09-Dec-2010, tatu: Would be nice to know which property pointed to this
-             *    bean... but, alas, no such information is retained, so:
-             */
-            subDeser = ctxt.findValueDeserializer(type, _property);
-            // Also, need to cache it
-            if (subDeser != null) {
-                synchronized (this) {
-                    if (_subDeserializers == null) {
-                        _subDeserializers = new HashMap<ClassKey,JsonDeserializer<Object>>();;
-                    }
-                    _subDeserializers.put(new ClassKey(bean.getClass()), subDeser);
-                }            
-            }
+        JavaType type = ctxt.constructType(bean.getClass());
+        /* 09-Dec-2010, tatu: Would be nice to know which property pointed to this
+         *    bean... but, alas, no such information is retained, so:
+         */
+        subDeser = ctxt.findValueDeserializer(type, _property);
+        // Also, need to cache it
+        if (subDeser != null) {
+            synchronized (this) {
+                if (_subDeserializers == null) {
+                    _subDeserializers = new HashMap<ClassKey,JsonDeserializer<Object>>();;
+                }
+                _subDeserializers.put(new ClassKey(bean.getClass()), subDeser);
+            }            
         }
         return subDeser;
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java
index dea7683..b07d22a 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java
@@ -422,37 +422,26 @@
      * module interface).
      */
     @Override
-    public ValueInstantiator findValueInstantiator(DeserializationConfig config,
+    public ValueInstantiator findValueInstantiator(DeserializationContext ctxt,
             BeanDescription beanDesc)
         throws JsonMappingException
     {
-        ValueInstantiator instantiator;
+        final DeserializationConfig config = ctxt.getConfig();
+
+        ValueInstantiator instantiator = null;
         // [JACKSON-633] Check @JsonValueInstantiator before anything else
         AnnotatedClass ac = beanDesc.getClassInfo();
-        Object instDef = config.getAnnotationIntrospector().findValueInstantiator(ac);
+        Object instDef = ctxt.getAnnotationIntrospector().findValueInstantiator(ac);
         if (instDef != null) {
-            if (instDef instanceof ValueInstantiator) {
-                instantiator = (ValueInstantiator) instDef;
-            } else {
-                if (!(instDef instanceof Class<?>)) { // sanity check
-                    throw new IllegalStateException("Invalid value instantiator returned for type "+beanDesc+": neither a Class nor ValueInstantiator");
-                }
-                Class<?> cls = (Class<?>) instDef;
-                if (!ValueInstantiator.class.isAssignableFrom(cls)) {
-                    throw new IllegalStateException("Invalid instantiator Class<?> returned for type "+beanDesc+": "
-                            +cls.getName()+" not a ValueInstantiator");
-                }
-                @SuppressWarnings("unchecked")
-                Class<? extends ValueInstantiator> instClass = (Class<? extends ValueInstantiator>) cls;
-                instantiator = config.valueInstantiatorInstance(ac, (Class<? extends ValueInstantiator>)instClass);
-            }
-        } else {
+            instantiator = valueInstantiatorInstance(config, ac, instDef);
+        }
+        if (instantiator == null) {
             /* Second: see if some of standard Jackson/JDK types might provide value
              * instantiators.
              */
             instantiator = findStdValueInstantiator(config, beanDesc);
             if (instantiator == null) {
-                instantiator = constructDefaultValueInstantiator(config, beanDesc);
+                instantiator = constructDefaultValueInstantiator(ctxt, beanDesc);
             }
         }
         
@@ -477,10 +466,11 @@
      * enums.
      */
     @Override
-    public JsonDeserializer<Object> createBeanDeserializer(DeserializationConfig config,
+    public JsonDeserializer<Object> createBeanDeserializer(DeserializationContext ctxt,
             JavaType type, BeanDescription beanDesc, BeanProperty property)
         throws JsonMappingException
     {
+        final DeserializationConfig config = ctxt.getConfig();
         // We may also have custom overrides:
         JsonDeserializer<Object> custom = _findCustomBeanDeserializer(type, config, beanDesc, property);
         if (custom != null) {
@@ -491,7 +481,7 @@
          * different handling.
          */
         if (type.isThrowable()) {
-            return buildThrowableDeserializer(config, type, beanDesc, property);
+            return buildThrowableDeserializer(ctxt, type, beanDesc, property);
         }
         /* Or, for abstract types, may have alternate means for resolution
          * (defaulting, materialization)
@@ -504,7 +494,7 @@
                  * interface doesn't have constructors, for one)
                  */
                 beanDesc = config.introspect(concreteType);
-                return buildBeanDeserializer(config, concreteType, beanDesc, property);
+                return buildBeanDeserializer(ctxt, concreteType, beanDesc, property);
             }
         }
 
@@ -519,7 +509,7 @@
             return null;
         }
         // Use generic bean introspection to build deserializer
-        return buildBeanDeserializer(config, type, beanDesc, property);
+        return buildBeanDeserializer(ctxt, type, beanDesc, property);
     }
 
     /**
@@ -574,12 +564,13 @@
      * deserializers.
      */
     @SuppressWarnings("unchecked")
-    public JsonDeserializer<Object> buildBeanDeserializer(DeserializationConfig config,
+    public JsonDeserializer<Object> buildBeanDeserializer(DeserializationContext ctxt,
             JavaType type, BeanDescription beanDesc, BeanProperty property)
         throws JsonMappingException
     {
         // First: check what creators we can use, if any
-        ValueInstantiator valueInstantiator = findValueInstantiator(config, beanDesc);
+        ValueInstantiator valueInstantiator = findValueInstantiator(ctxt, beanDesc);
+        final DeserializationConfig config = ctxt.getConfig();
         // ... since often we have nothing to go on, if we have abstract type:
         if (type.isAbstract()) {
             if (!valueInstantiator.canInstantiate()) {
@@ -590,10 +581,10 @@
         BeanDeserializerBuilder builder = constructBeanDeserializerBuilder(beanDesc);
         builder.setValueInstantiator(valueInstantiator);
          // And then setters for deserializing from JSON Object
-        addBeanProps(config, beanDesc, builder);
+        addBeanProps(ctxt, beanDesc, builder);
         // managed/back reference fields/setters need special handling... first part
-        addReferenceProperties(config, beanDesc, builder);
-        addInjectables(config, beanDesc, builder);
+        addReferenceProperties(ctxt, beanDesc, builder);
+        addInjectables(ctxt, beanDesc, builder);
 
         // [JACKSON-440]: update builder now that all information is in?
         if (_factoryConfig.hasDeserializerModifiers()) {
@@ -614,15 +605,16 @@
     }
 
     @SuppressWarnings("unchecked")
-    public JsonDeserializer<Object> buildThrowableDeserializer(DeserializationConfig config,
+    public JsonDeserializer<Object> buildThrowableDeserializer(DeserializationContext ctxt,
             JavaType type, BeanDescription beanDesc, BeanProperty property)
         throws JsonMappingException
     {
+        final DeserializationConfig config = ctxt.getConfig();
         // first: construct like a regular bean deserializer...
         BeanDeserializerBuilder builder = constructBeanDeserializerBuilder(beanDesc);
-        builder.setValueInstantiator(findValueInstantiator(config, beanDesc));
+        builder.setValueInstantiator(findValueInstantiator(ctxt, beanDesc));
 
-        addBeanProps(config, beanDesc, builder);
+        addBeanProps(ctxt, beanDesc, builder);
         // (and assume there won't be any back references)
 
         // But then let's decorate things a bit
@@ -631,7 +623,7 @@
          */
         AnnotatedMethod am = beanDesc.findMethod("initCause", INIT_CAUSE_PARAMS);
         if (am != null) { // should never be null
-            SettableBeanProperty prop = constructSettableProperty(config, beanDesc, "cause", am);
+            SettableBeanProperty prop = constructSettableProperty(ctxt, beanDesc, "cause", am);
             if (prop != null) {
                 /* 21-Aug-2011, tatus: We may actually have found 'cause' property
                  *   to set (with new 1.9 code)... but let's replace it just in case,
@@ -699,13 +691,13 @@
      * Method that will construct standard default {@link ValueInstantiator}
      * using annotations (like @JsonCreator) and visibility rules
      */
-    protected ValueInstantiator constructDefaultValueInstantiator(DeserializationConfig config,
+    protected ValueInstantiator constructDefaultValueInstantiator(DeserializationContext ctxt,
             BeanDescription beanDesc)
         throws JsonMappingException
     {
-        boolean fixAccess = config.canOverrideAccessModifiers();
+        boolean fixAccess = ctxt.canOverrideAccessModifiers();
         CreatorCollector creators =  new CreatorCollector(beanDesc, fixAccess);
-        AnnotationIntrospector intr = config.getAnnotationIntrospector();
+        AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
         
         // First, let's figure out constructor/factory-based instantiation
         // 23-Jan-2010, tatus: but only for concrete types
@@ -720,20 +712,21 @@
         }
 
         // need to construct suitable visibility checker:
+        final DeserializationConfig config = ctxt.getConfig();
         VisibilityChecker<?> vchecker = config.getDefaultVisibilityChecker();
         vchecker = config.getAnnotationIntrospector().findAutoDetectVisibility(beanDesc.getClassInfo(), vchecker);
 
         /* Important: first add factory methods; then constructors, so
          * latter can override former!
          */
-        _addDeserializerFactoryMethods(config, beanDesc, vchecker, intr, creators);
-        _addDeserializerConstructors(config, beanDesc, vchecker, intr, creators);
+        _addDeserializerFactoryMethods(ctxt, beanDesc, vchecker, intr, creators);
+        _addDeserializerConstructors(ctxt, beanDesc, vchecker, intr, creators);
 
         return creators.constructValueInstantiator(config);
     }
 
     protected void _addDeserializerConstructors
-        (DeserializationConfig config, BeanDescription beanDesc, VisibilityChecker<?> vchecker,
+        (DeserializationContext ctxt, BeanDescription beanDesc, VisibilityChecker<?> vchecker,
          AnnotationIntrospector intr, CreatorCollector creators)
         throws JsonMappingException
     {
@@ -746,7 +739,7 @@
             boolean isVisible =  vchecker.isCreatorVisible(ctor);
             // some single-arg constructors (String, number) are auto-detected
             if (argCount == 1) {
-                _handleSingleArgumentConstructor(config, beanDesc, vchecker, intr, creators,
+                _handleSingleArgumentConstructor(ctxt, beanDesc, vchecker, intr, creators,
                         ctor, isCreator, isVisible);
                 continue;
             }
@@ -769,10 +762,10 @@
                 Object injectId = intr.findInjectableValueId(param);
                 if (name != null && name.length() > 0) {
                     ++namedCount;
-                    properties[i] = constructCreatorProperty(config, beanDesc, name, i, param, injectId);
+                    properties[i] = constructCreatorProperty(ctxt, beanDesc, name, i, param, injectId);
                 } else if (injectId != null) {
                     ++injectCount;
-                    properties[i] = constructCreatorProperty(config, beanDesc, name, i, param, injectId);
+                    properties[i] = constructCreatorProperty(ctxt, beanDesc, name, i, param, injectId);
                 } else if (nonAnnotatedParam == null) {
                     nonAnnotatedParam = param;
                 }
@@ -793,7 +786,7 @@
         }
     }
 
-    protected boolean _handleSingleArgumentConstructor(DeserializationConfig config,
+    protected boolean _handleSingleArgumentConstructor(DeserializationContext ctxt,
             BeanDescription beanDesc, VisibilityChecker<?> vchecker,
             AnnotationIntrospector intr, CreatorCollector creators,
             AnnotatedConstructor ctor, boolean isCreator, boolean isVisible)
@@ -807,7 +800,7 @@
         if ((injectId != null) || (name != null && name.length() > 0)) { // property-based
             // We know there's a name and it's only 1 parameter.
             CreatorProperty[] properties = new CreatorProperty[1];
-            properties[0] = constructCreatorProperty(config, beanDesc, name, 0, param, injectId);
+            properties[0] = constructCreatorProperty(ctxt, beanDesc, name, 0, param, injectId);
             creators.addPropertyCreator(ctor, properties);
             return true;
         }
@@ -848,11 +841,11 @@
     }
     
     protected void _addDeserializerFactoryMethods
-        (DeserializationConfig config, BeanDescription beanDesc, VisibilityChecker<?> vchecker,
+        (DeserializationContext ctxt, BeanDescription beanDesc, VisibilityChecker<?> vchecker,
          AnnotationIntrospector intr, CreatorCollector creators)
         throws JsonMappingException
     {
-
+        final DeserializationConfig config = ctxt.getConfig();
         for (AnnotatedMethod factory : beanDesc.getFactoryMethods()) {
             int argCount = factory.getParameterCount();
             if (argCount < 1) {
@@ -889,10 +882,10 @@
                 Object injectId = intr.findInjectableValueId(param);
                 if (name != null && name.length() > 0) {
                     ++namedCount;
-                    properties[i] = constructCreatorProperty(config, beanDesc, name, i, param, injectId);
+                    properties[i] = constructCreatorProperty(ctxt, beanDesc, name, i, param, injectId);
                 } else if (injectId != null) {
                     ++injectCount;
-                    properties[i] = constructCreatorProperty(config, beanDesc, name, i, param, injectId);
+                    properties[i] = constructCreatorProperty(ctxt, beanDesc, name, i, param, injectId);
                 } else if (nonAnnotatedParam == null) {
                     nonAnnotatedParam = param;
                 }
@@ -964,22 +957,23 @@
      * a logical property passed via Creator (constructor or static
      * factory method)
      */
-    protected CreatorProperty constructCreatorProperty(DeserializationConfig config,
+    protected CreatorProperty constructCreatorProperty(DeserializationContext ctxt,
             BeanDescription beanDesc, String name, int index,
             AnnotatedParameter param,
             Object injectableValueId)
         throws JsonMappingException
     {
+        final DeserializationConfig config = ctxt.getConfig();
         JavaType t0 = config.getTypeFactory().constructType(param.getParameterType(), beanDesc.bindingsForBeanType());
         BeanProperty.Std property = new BeanProperty.Std(name, t0, beanDesc.getClassAnnotations(), param);
-        JavaType type = resolveType(config, beanDesc, t0, param, property);
+        JavaType type = resolveType(ctxt, beanDesc, t0, param, property);
         if (type != t0) {
             property = property.withType(type);
         }
         // Is there an annotation that specifies exact deserializer?
-        JsonDeserializer<Object> deser = findDeserializerFromAnnotation(config, param, property);
+        JsonDeserializer<Object> deser = findDeserializerFromAnnotation(ctxt, param, property);
         // If yes, we are mostly done:
-        type = modifyTypeByAnnotation(config, param, type, name);
+        type = modifyTypeByAnnotation(ctxt, param, type, property);
 
         // Type deserializer: either comes from property (and already resolved)
         TypeDeserializer typeDeser = (TypeDeserializer) type.getTypeHandler();
@@ -1002,13 +996,13 @@
      * Note: designed to be overridable, and effort is made to keep interface
      * similar between versions.
      */
-    protected void addBeanProps(DeserializationConfig config,
+    protected void addBeanProps(DeserializationContext ctxt,
             BeanDescription beanDesc, BeanDeserializerBuilder builder)
         throws JsonMappingException
     {
         List<BeanPropertyDefinition> props = beanDesc.findProperties();
         // Things specified as "ok to ignore"? [JACKSON-77]
-        AnnotationIntrospector intr = config.getAnnotationIntrospector();
+        AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
         boolean ignoreAny = false;
         {
             Boolean B = intr.findIgnoreUnknownProperties(beanDesc.getClassInfo());
@@ -1025,7 +1019,7 @@
         // Also, do we have a fallback "any" setter?
         AnnotatedMethod anySetter = beanDesc.findAnySetter();
         if (anySetter != null) {
-            builder.setAnySetter(constructAnySetter(config, beanDesc, anySetter));
+            builder.setAnySetter(constructAnySetter(ctxt, beanDesc, anySetter));
         }
         // NOTE: we do NOT add @JsonIgnore'd properties into blocked ones if there's any setter
         // Implicit ones via @JsonIgnore and equivalent?
@@ -1061,12 +1055,12 @@
                 AnnotatedMethod setter = property.getSetter();
                 // [JACKSON-429] Some types are declared as ignorable as well
                 Class<?> type = setter.getParameterClass(0);
-                if (isIgnorableType(config, beanDesc, type, ignoredTypes)) {
+                if (isIgnorableType(ctxt.getConfig(), beanDesc, type, ignoredTypes)) {
                     // important: make ignorable, to avoid errors if value is actually seen
                     builder.addIgnorable(name);
                     continue;
                 }
-                SettableBeanProperty prop = constructSettableProperty(config, beanDesc, name, setter);
+                SettableBeanProperty prop = constructSettableProperty(ctxt, beanDesc, name, setter);
                 if (prop != null) {
                     builder.addProperty(prop);
                 }
@@ -1076,12 +1070,12 @@
                 AnnotatedField field = property.getField();
                 // [JACKSON-429] Some types are declared as ignorable as well
                 Class<?> type = field.getRawType();
-                if (isIgnorableType(config, beanDesc, type, ignoredTypes)) {
+                if (isIgnorableType(ctxt.getConfig(), beanDesc, type, ignoredTypes)) {
                     // important: make ignorable, to avoid errors if value is actually seen
                     builder.addIgnorable(name);
                     continue;
                 }
-                SettableBeanProperty prop = constructSettableProperty(config, beanDesc, name, field);
+                SettableBeanProperty prop = constructSettableProperty(ctxt, beanDesc, name, field);
                 if (prop != null) {
                     builder.addProperty(prop);
                 }
@@ -1094,7 +1088,7 @@
         /* also, as per [JACKSON-328], should not override fields (or actual setters),
          * thus these are added AFTER adding fields
          */
-        if (config.isEnabled(MapperConfig.Feature.USE_GETTERS_AS_SETTERS)) {
+        if (ctxt.isEnabled(MapperConfig.Feature.USE_GETTERS_AS_SETTERS)) {
             /* Hmmh. We have to assume that 'use getters as setters' also
              * implies 'yes, do auto-detect these getters'? (if not, we'd
              * need to add AUTO_DETECT_GETTERS to deser config too, not
@@ -1111,7 +1105,7 @@
                     Class<?> rt = getter.getRawType();
                     if (Collection.class.isAssignableFrom(rt) || Map.class.isAssignableFrom(rt)) {
                         if (!ignored.contains(name) && !builder.hasProperty(name)) {
-                            builder.addProperty(constructSetterlessProperty(config, beanDesc, name, getter));
+                            builder.addProperty(constructSetterlessProperty(ctxt, beanDesc, name, getter));
                         }
                     }
                 }
@@ -1123,7 +1117,7 @@
      * Method that will find if bean has any managed- or back-reference properties,
      * and if so add them to bean, to be linked during resolution phase.
      */
-    protected void addReferenceProperties(DeserializationConfig config,
+    protected void addReferenceProperties(DeserializationContext ctxt,
             BeanDescription beanDesc, BeanDeserializerBuilder builder)
         throws JsonMappingException
     {
@@ -1135,10 +1129,10 @@
                 AnnotatedMember m = en.getValue();
                 if (m instanceof AnnotatedMethod) {
                     builder.addBackReferenceProperty(name, constructSettableProperty(
-                            config, beanDesc, m.getName(), (AnnotatedMethod) m));
+                            ctxt, beanDesc, m.getName(), (AnnotatedMethod) m));
                 } else {
                     builder.addBackReferenceProperty(name, constructSettableProperty(
-                            config, beanDesc, m.getName(), (AnnotatedField) m));
+                            ctxt, beanDesc, m.getName(), (AnnotatedField) m));
                 }
             }
         }
@@ -1148,13 +1142,13 @@
      * Method called locate all members used for value injection (if any),
      * constructor {@link com.fasterxml.jackson.databind.deser.impl.ValueInjector} instances, and add them to builder.
      */
-    protected void addInjectables(DeserializationConfig config,
+    protected void addInjectables(DeserializationContext ctxt,
             BeanDescription beanDesc, BeanDeserializerBuilder builder)
         throws JsonMappingException
     {
         Map<Object, AnnotatedMember> raw = beanDesc.findInjectables();
         if (raw != null) {
-            boolean fixAccess = config.canOverrideAccessModifiers();
+            boolean fixAccess = ctxt.canOverrideAccessModifiers();
             for (Map.Entry<Object, AnnotatedMember> entry : raw.entrySet()) {
                 AnnotatedMember m = entry.getValue();
                 if (fixAccess) {
@@ -1171,31 +1165,31 @@
      * for handling unknown bean properties, given a method that
      * has been designated as such setter.
      */
-    protected SettableAnyProperty constructAnySetter(DeserializationConfig config,
+    protected SettableAnyProperty constructAnySetter(DeserializationContext ctxt,
             BeanDescription beanDesc, AnnotatedMethod setter)
         throws JsonMappingException
     {
-        if (config.canOverrideAccessModifiers()) {
+        if (ctxt.canOverrideAccessModifiers()) {
             setter.fixAccess(); // to ensure we can call it
         }
         // we know it's a 2-arg method, second arg is the value
         JavaType type = beanDesc.bindingsForBeanType().resolveType(setter.getParameterType(1));
         BeanProperty.Std property = new BeanProperty.Std(setter.getName(), type, beanDesc.getClassAnnotations(), setter);
-        type = resolveType(config, beanDesc, type, setter, property);
+        type = resolveType(ctxt, beanDesc, type, setter, property);
 
         /* AnySetter can be annotated with @JsonClass (etc) just like a
          * regular setter... so let's see if those are used.
          * Returns null if no annotations, in which case binding will
          * be done at a later point.
          */
-        JsonDeserializer<Object> deser = findDeserializerFromAnnotation(config, setter, property);
+        JsonDeserializer<Object> deser = findDeserializerFromAnnotation(ctxt, setter, property);
         if (deser != null) {
             return new SettableAnyProperty(property, setter, type, deser);
         }
         /* Otherwise, method may specify more specific (sub-)class for
          * value (no need to check if explicit deser was specified):
          */
-        type = modifyTypeByAnnotation(config, setter, type, property.getName());
+        type = modifyTypeByAnnotation(ctxt, setter, type, property);
         return new SettableAnyProperty(property, setter, type, null);
     }
 
@@ -1209,20 +1203,20 @@
      * @return Property constructed, if any; or null to indicate that
      *   there should be no property based on given definitions.
      */
-    protected SettableBeanProperty constructSettableProperty(DeserializationConfig config,
+    protected SettableBeanProperty constructSettableProperty(DeserializationContext ctxt,
             BeanDescription beanDesc, String name,
             AnnotatedMethod setter)
         throws JsonMappingException
     {
         // need to ensure method is callable (for non-public)
-        if (config.canOverrideAccessModifiers()) {
+        if (ctxt.canOverrideAccessModifiers()) {
             setter.fixAccess();
         }
 
         // note: this works since we know there's exactly one argument for methods
         JavaType t0 = beanDesc.bindingsForBeanType().resolveType(setter.getParameterType(0));
         BeanProperty.Std property = new BeanProperty.Std(name, t0, beanDesc.getClassAnnotations(), setter);
-        JavaType type = resolveType(config, beanDesc, t0, setter, property);
+        JavaType type = resolveType(ctxt, beanDesc, t0, setter, property);
         // did type change?
         if (type != t0) {
             property = property.withType(type);
@@ -1231,8 +1225,8 @@
         /* First: does the Method specify the deserializer to use?
          * If so, let's use it.
          */
-        JsonDeserializer<Object> propDeser = findDeserializerFromAnnotation(config, setter, property);
-        type = modifyTypeByAnnotation(config, setter, type, name);
+        JsonDeserializer<Object> propDeser = findDeserializerFromAnnotation(ctxt, setter, property);
+        type = modifyTypeByAnnotation(ctxt, setter, type, property);
         TypeDeserializer typeDeser = type.getTypeHandler();
         SettableBeanProperty prop = new SettableBeanProperty.MethodProperty(name, type, typeDeser,
                 beanDesc.getClassAnnotations(), setter);
@@ -1240,24 +1234,24 @@
             prop = prop.withValueDeserializer(propDeser);
         }
         // [JACKSON-235]: need to retain name of managed forward references:
-        AnnotationIntrospector.ReferenceProperty ref = config.getAnnotationIntrospector().findReferenceType(setter);
+        AnnotationIntrospector.ReferenceProperty ref = ctxt.getAnnotationIntrospector().findReferenceType(setter);
         if (ref != null && ref.isManagedReference()) {
             prop.setManagedReferenceName(ref.getName());
         }
         return prop;
     }
 
-    protected SettableBeanProperty constructSettableProperty(DeserializationConfig config,
+    protected SettableBeanProperty constructSettableProperty(DeserializationContext ctxt,
             BeanDescription beanDesc, String name, AnnotatedField field)
         throws JsonMappingException
     {
         // need to ensure method is callable (for non-public)
-        if (config.canOverrideAccessModifiers()) {
+        if (ctxt.canOverrideAccessModifiers()) {
             field.fixAccess();
         }
         JavaType t0 = beanDesc.bindingsForBeanType().resolveType(field.getGenericType());
         BeanProperty.Std property = new BeanProperty.Std(name, t0, beanDesc.getClassAnnotations(), field);
-        JavaType type = resolveType(config, beanDesc, t0, field, property);
+        JavaType type = resolveType(ctxt, beanDesc, t0, field, property);
         // did type change?
         if (type != t0) {
             property = property.withType(type);
@@ -1265,8 +1259,8 @@
         /* First: does the Method specify the deserializer to use?
          * If so, let's use it.
          */
-        JsonDeserializer<Object> propDeser = findDeserializerFromAnnotation(config, field, property);
-        type = modifyTypeByAnnotation(config, field, type, name);
+        JsonDeserializer<Object> propDeser = findDeserializerFromAnnotation(ctxt, field, property);
+        type = modifyTypeByAnnotation(ctxt, field, type, property);
         TypeDeserializer typeDeser = type.getTypeHandler();
         SettableBeanProperty prop = new SettableBeanProperty.FieldProperty(name, type, typeDeser,
                 beanDesc.getClassAnnotations(), field);
@@ -1274,7 +1268,7 @@
             prop = prop.withValueDeserializer(propDeser);
         }
         // [JACKSON-235]: need to retain name of managed forward references:
-        AnnotationIntrospector.ReferenceProperty ref = config.getAnnotationIntrospector().findReferenceType(field);
+        AnnotationIntrospector.ReferenceProperty ref = ctxt.getAnnotationIntrospector().findReferenceType(field);
         if (ref != null && ref.isManagedReference()) {
             prop.setManagedReferenceName(ref.getName());
         }
@@ -1288,12 +1282,12 @@
      * @param getter Method to use to get property value to modify, null if
      *    none. Non-null for "setterless" properties.
      */
-    protected SettableBeanProperty constructSetterlessProperty(DeserializationConfig config,
+    protected SettableBeanProperty constructSetterlessProperty(DeserializationContext ctxt,
             BeanDescription beanDesc, String name, AnnotatedMethod getter)
         throws JsonMappingException
     {
         // need to ensure it is callable now:
-        if (config.canOverrideAccessModifiers()) {
+        if (ctxt.canOverrideAccessModifiers()) {
             getter.fixAccess();
         }
 
@@ -1303,8 +1297,8 @@
          */
         BeanProperty.Std property = new BeanProperty.Std(name, type, beanDesc.getClassAnnotations(), getter);
         // @TODO: create BeanProperty to pass?
-        JsonDeserializer<Object> propDeser = findDeserializerFromAnnotation(config, getter, property);
-        type = modifyTypeByAnnotation(config, getter, type, name);
+        JsonDeserializer<Object> propDeser = findDeserializerFromAnnotation(ctxt, getter, property);
+        type = modifyTypeByAnnotation(ctxt, getter, type, property);
         TypeDeserializer typeDeser = type.getTypeHandler();
         SettableBeanProperty prop = new SettableBeanProperty.SetterlessProperty(name, type, typeDeser,
                 beanDesc.getClassAnnotations(), getter);
@@ -1376,7 +1370,7 @@
      *
      * @param a Method or field that the type is associated with
      * @param type Type derived from the setter argument
-     * @param propName Name of property that refers to type, if any; null
+     * @param prop property that refers to type, if any; null
      *   if no property information available (when modify type declaration
      *   of a class, for example)
      *
@@ -1386,13 +1380,14 @@
      * @throws JsonMappingException if invalid annotation is found
      */
     @SuppressWarnings({ "unchecked" })
-    protected <T extends JavaType> T modifyTypeByAnnotation(DeserializationConfig config,
-            Annotated a, T type, String propName)
+    protected <T extends JavaType> T modifyTypeByAnnotation(DeserializationContext ctxt,
+            Annotated a, T type, BeanProperty prop)
         throws JsonMappingException
     {
         // first: let's check class for the instance itself:
-        AnnotationIntrospector intr = config.getAnnotationIntrospector();
-        Class<?> subclass = intr.findDeserializationType(a, type, propName);
+        AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
+        Class<?> subclass = intr.findDeserializationType(a, type,
+                (prop == null) ? null : prop.getName());
         if (subclass != null) {
             try {
                 type = (T) type.narrowBy(subclass);
@@ -1403,7 +1398,8 @@
 
         // then key class
         if (type.isContainerType()) {
-            Class<?> keyClass = intr.findDeserializationKeyType(a, type.getKeyType(), propName);
+            Class<?> keyClass = intr.findDeserializationKeyType(a, type.getKeyType(),
+                    (prop == null) ? null : prop.getName());
             if (keyClass != null) {
                 // illegal to use on non-Maps
                 if (!(type instanceof MapLikeType)) {
@@ -1422,25 +1418,16 @@
              */
             if (keyType != null && keyType.getValueHandler() == null) {
                 Object kdDef = intr.findKeyDeserializer(a);
-                if (kdDef != null) {
-                    KeyDeserializer kd = null;
-                    if (kdDef instanceof KeyDeserializer) {
-                        kd = (KeyDeserializer) kdDef;
-                    } else {
-                        Class<?> kdClass = _verifyAsClass(kdDef, "findKeyDeserializer", KeyDeserializer.None.class);
-                        if (kdClass != null) {
-                            kd = config.keyDeserializerInstance(a, kdClass);
-                        }
-                    }
-                    if (kd != null) {
-                        type = (T) ((MapLikeType) type).withKeyValueHandler(kd);
-                        keyType = type.getKeyType(); // just in case it's used below
-                    }
+                KeyDeserializer kd = ctxt.keyDeserializerInstance(a, prop, kdDef);
+                if (kd != null) {
+                    type = (T) ((MapLikeType) type).withKeyValueHandler(kd);
+                    keyType = type.getKeyType(); // just in case it's used below
                 }
             }            
            
            // and finally content class; only applicable to structured types
-           Class<?> cc = intr.findDeserializationContentType(a, type.getContentType(), propName);
+           Class<?> cc = intr.findDeserializationContentType(a, type.getContentType(),
+                   (prop == null) ? null : prop.getName());
            if (cc != null) {
                try {
                    type = (T) type.narrowContentsBy(cc);
@@ -1452,19 +1439,9 @@
            JavaType contentType = type.getContentType();
            if (contentType.getValueHandler() == null) { // as with above, avoid resetting (which would trigger exception)
                Object cdDef = intr.findContentDeserializer(a);
-                if (cdDef != null) {
-                    JsonDeserializer<?> cd = null;
-                    if (cdDef instanceof JsonDeserializer<?>) {
-                        cdDef = (JsonDeserializer<?>) cdDef;
-                    } else {
-                        Class<?> cdClass = _verifyAsClass(cdDef, "findContentDeserializer", JsonDeserializer.None.class);
-                        if (cdClass != null) {
-                            cd = config.deserializerInstance(a, cdClass);
-                        }
-                    }
-                    if (cd != null) {
-                        type = (T) type.withContentValueHandler(cd);
-                    }
+                JsonDeserializer<?> cd = ctxt.deserializerInstance(a, prop, cdDef);
+                if (cd != null) {
+                    type = (T) type.withContentValueHandler(cd);
                 }
             }
         }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/DeserializerCache.java b/src/main/java/com/fasterxml/jackson/databind/deser/DeserializerCache.java
index 8129379..1c32281 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/DeserializerCache.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/DeserializerCache.java
@@ -236,18 +236,22 @@
      *   accessing suitable key deserializer; including that of not
      *   finding any serializer
      */
-    public KeyDeserializer findKeyDeserializer(DeserializationConfig config,
+    public KeyDeserializer findKeyDeserializer(DeserializationContext ctxt,
             JavaType type, BeanProperty property)
         throws JsonMappingException
     {
-        KeyDeserializer kd = _factory.createKeyDeserializer(config, type, property);
-        // One more thing: contextuality
-        if (kd instanceof ContextualKeyDeserializer) {
-            kd = ((ContextualKeyDeserializer) kd).createContextual(config, property);
-        }
+        KeyDeserializer kd = _factory.createKeyDeserializer(ctxt, type, property);
         if (kd == null) { // if none found, need to use a placeholder that'll fail
             return _handleUnknownKeyDeserializer(type);
         }
+        // First: need to resolve?
+        if (kd instanceof ResolvableDeserializer) {
+            ((ResolvableDeserializer) kd).resolve(ctxt);
+        }
+        // Second: contextualize?
+        if (kd instanceof ContextualKeyDeserializer) {
+            kd = ((ContextualKeyDeserializer) kd).createContextual(ctxt.getConfig(), property);
+        }
         return kd;
     }
 
@@ -409,7 +413,7 @@
         }
 
         // If not, may have further type-modification annotations to check:
-        JavaType newType = modifyTypeByAnnotation(config, beanDesc.getClassInfo(), type, property);
+        JavaType newType = modifyTypeByAnnotation(ctxt, beanDesc.getClassInfo(), type, property);
         if (newType != type) {
             type = newType;
             beanDesc = config.introspect(newType);
@@ -417,30 +421,30 @@
 
         // If not, let's see which factory method to use:
         if (type.isEnumType()) {
-            return (JsonDeserializer<Object>) _factory.createEnumDeserializer(config, type,
+            return (JsonDeserializer<Object>) _factory.createEnumDeserializer(ctxt, type,
                     beanDesc, property);
         }
         if (type.isContainerType()) {
             if (type.isArrayType()) {
-                return (JsonDeserializer<Object>)_factory.createArrayDeserializer(config,
+                return (JsonDeserializer<Object>)_factory.createArrayDeserializer(ctxt,
                         (ArrayType) type, beanDesc, property);
             }
             if (type.isMapLikeType()) {
                 MapLikeType mlt = (MapLikeType) type;
                 if (mlt.isTrueMapType()) {
-                    return (JsonDeserializer<Object>)_factory.createMapDeserializer(config,
+                    return (JsonDeserializer<Object>)_factory.createMapDeserializer(ctxt,
                             (MapType) mlt, beanDesc, property);
                 }
-                return (JsonDeserializer<Object>)_factory.createMapLikeDeserializer(config,
+                return (JsonDeserializer<Object>)_factory.createMapLikeDeserializer(ctxt,
                         mlt, beanDesc, property);
             }
             if (type.isCollectionLikeType()) {
                 CollectionLikeType clt = (CollectionLikeType) type;
                 if (clt.isTrueCollectionType()) {
-                    return (JsonDeserializer<Object>)_factory.createCollectionDeserializer(config,
+                    return (JsonDeserializer<Object>)_factory.createCollectionDeserializer(ctxt,
                             (CollectionType) clt, beanDesc, property);
                 }
-                return (JsonDeserializer<Object>)_factory.createCollectionLikeDeserializer(config,
+                return (JsonDeserializer<Object>)_factory.createCollectionLikeDeserializer(ctxt,
                         clt, beanDesc, property);
             }
         }
@@ -449,7 +453,7 @@
         if (JsonNode.class.isAssignableFrom(type.getRawClass())) {
             return (JsonDeserializer<Object>)_factory.createTreeDeserializer(config, type, beanDesc, property);
         }
-        return (JsonDeserializer<Object>)_factory.createBeanDeserializer(config, type, beanDesc, property);
+        return (JsonDeserializer<Object>)_factory.createBeanDeserializer(ctxt, type, beanDesc, property);
     }
 
     /**
@@ -457,7 +461,6 @@
      * has annotation that tells which class to use for deserialization.
      * Returns null if no such annotation found.
      */
-    @SuppressWarnings("unchecked")
     protected JsonDeserializer<Object> findDeserializerFromAnnotation(DeserializationContext ctxt,
             Annotated ann, BeanProperty property)
         throws JsonMappingException
@@ -466,38 +469,7 @@
         if (deserDef == null) {
             return null;
         }
-        if (deserDef instanceof JsonDeserializer) {
-            JsonDeserializer<Object> deser = (JsonDeserializer<Object>) deserDef;
-            // related to [JACKSON-569], need contextualization:
-            if (deser instanceof ContextualDeserializer<?>) {
-                deser = (JsonDeserializer<Object>)((ContextualDeserializer<?>) deser).createContextual(ctxt.getConfig(), property);
-            }
-            return deser;
-        }
-        /* Alas, there's no way to force return type of "either class
-         * X or Y" -- need to throw an exception after the fact
-         */
-        if (!(deserDef instanceof Class)) {
-            throw new IllegalStateException("AnnotationIntrospector returned deserializer definition of type "+deserDef.getClass().getName()+"; expected type JsonDeserializer or Class<JsonDeserializer> instead");
-        }
-        Class<? extends JsonDeserializer<?>> deserClass = (Class<? extends JsonDeserializer<?>>) deserDef;
-        if (!JsonDeserializer.class.isAssignableFrom(deserClass)) {
-            throw new IllegalStateException("AnnotationIntrospector returned Class "+deserClass.getName()+"; expected Class<JsonDeserializer>");
-        }
-        JsonDeserializer<Object> deser = ctxt.getConfig().deserializerInstance(ann, deserClass);
-        // related to [JACKSON-569], need contextualization:
-        if (deser instanceof ContextualDeserializer<?>) {
-            deser = (JsonDeserializer<Object>)((ContextualDeserializer<?>) deser).createContextual(ctxt.getConfig(), property);
-        }
-        return deser;
-    }
-    
-    private JavaType modifyTypeByAnnotation(DeserializationConfig config,
-            Annotated a, JavaType type, BeanProperty prop)
-        throws JsonMappingException
-    {
-        return modifyTypeByAnnotation(config, a, type,
-                (prop == null)  ? null : prop.getName());
+        return ctxt.deserializerInstance(ann, property, deserDef);
     }
 
     /**
@@ -510,22 +482,21 @@
      *
      * @param a Method or field that the type is associated with
      * @param type Type derived from the setter argument
-     * @param propName Name of property that refers to type, if any; null
-     *   if no property information available (when modify type declaration
-     *   of a class, for example)
+     * @param prop Property that lead to this annotation, if any.
      *
      * @return Original type if no annotations are present; or a more
      *   specific type derived from it if type annotation(s) was found
      *
      * @throws JsonMappingException if invalid annotation is found
      */
-    private JavaType modifyTypeByAnnotation(DeserializationConfig config,
-            Annotated a, JavaType type, String propName)
+    private JavaType modifyTypeByAnnotation(DeserializationContext ctxt,
+            Annotated a, JavaType type, BeanProperty prop)
         throws JsonMappingException
     {
         // first: let's check class for the instance itself:
-        AnnotationIntrospector intr = config.getAnnotationIntrospector();
-        Class<?> subclass = intr.findDeserializationType(a, type, propName);
+        AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
+        Class<?> subclass = intr.findDeserializationType(a, type,
+                (prop == null)? null : prop.getName());
         if (subclass != null) {
             try {
                 type = type.narrowBy(subclass);
@@ -536,7 +507,8 @@
 
         // then key class
         if (type.isContainerType()) {
-            Class<?> keyClass = intr.findDeserializationKeyType(a, type.getKeyType(), propName);
+            Class<?> keyClass = intr.findDeserializationKeyType(a, type.getKeyType(),
+                    (prop == null)? null : prop.getName());
             if (keyClass != null) {
                 // illegal to use on non-Maps
                 if (!(type instanceof MapLikeType)) {
@@ -556,15 +528,7 @@
             if (keyType != null && keyType.getValueHandler() == null) {
                 Object kdDef = intr.findKeyDeserializer(a);
                 if (kdDef != null) {
-                    KeyDeserializer kd = null;
-                    if (kdDef instanceof KeyDeserializer) {
-                        kd = (KeyDeserializer) kdDef;
-                    } else {
-                        Class<?> kdClass = _verifyAsClass(kdDef, "findKeyDeserializer", KeyDeserializer.None.class);
-                        if (kdClass != null) {
-                            kd = config.keyDeserializerInstance(a, kdClass);
-                        }
-                    }
+                    KeyDeserializer kd = ctxt.keyDeserializerInstance(a, prop, kdDef);
                     if (kd != null) {
                         type = ((MapLikeType) type).withKeyValueHandler(kd);
                         keyType = type.getKeyType(); // just in case it's used below
@@ -573,7 +537,8 @@
             }            
             
             // and finally content class; only applicable to structured types
-            Class<?> cc = intr.findDeserializationContentType(a, type.getContentType(), propName);
+            Class<?> cc = intr.findDeserializationContentType(a, type.getContentType(),
+                    (prop == null) ? null : prop.getName());
             if (cc != null) {
                 try {
                     type = type.narrowContentsBy(cc);
@@ -592,7 +557,7 @@
                     } else {
                         Class<?> cdClass = _verifyAsClass(cdDef, "findContentDeserializer", JsonDeserializer.None.class);
                         if (cdClass != null) {
-                            cd = config.deserializerInstance(a, cdClass);
+                            cd = ctxt.deserializerInstance(a, prop, cdClass);
                         }
                     }
                     if (cd != null) {
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/DeserializerFactory.java b/src/main/java/com/fasterxml/jackson/databind/deser/DeserializerFactory.java
index b28d095..d3ed96f 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/DeserializerFactory.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/DeserializerFactory.java
@@ -198,7 +198,7 @@
      * Method that is to find all creators (constructors, factory methods)
      * for the bean type to deserialize.
      */
-    public abstract ValueInstantiator findValueInstantiator(DeserializationConfig config,
+    public abstract ValueInstantiator findValueInstantiator(DeserializationContext ctxt,
             BeanDescription beanDesc)
         throws JsonMappingException;
     
@@ -214,7 +214,7 @@
      *
      * @param type Type to be deserialized
      */
-    public abstract JsonDeserializer<Object> createBeanDeserializer(DeserializationConfig config,
+    public abstract JsonDeserializer<Object> createBeanDeserializer(DeserializationContext ctxt,
             JavaType type, BeanDescription beanDesc, BeanProperty property)
         throws JsonMappingException;
 
@@ -225,27 +225,27 @@
      *
      * @param type Type to be deserialized
      */
-    public abstract JsonDeserializer<?> createArrayDeserializer(DeserializationConfig config,
+    public abstract JsonDeserializer<?> createArrayDeserializer(DeserializationContext ctxt,
             ArrayType type, BeanDescription beanDesc, BeanProperty property)
         throws JsonMappingException;
 
-    public abstract JsonDeserializer<?> createCollectionDeserializer(DeserializationConfig config,
+    public abstract JsonDeserializer<?> createCollectionDeserializer(DeserializationContext ctxt,
             CollectionType type, BeanDescription beanDesc, BeanProperty property)
         throws JsonMappingException;
 
-    public abstract JsonDeserializer<?> createCollectionLikeDeserializer(DeserializationConfig config,
+    public abstract JsonDeserializer<?> createCollectionLikeDeserializer(DeserializationContext ctxt,
             CollectionLikeType type, BeanDescription beanDesc, BeanProperty property)
         throws JsonMappingException;
     
-    public abstract JsonDeserializer<?> createEnumDeserializer(DeserializationConfig config,
+    public abstract JsonDeserializer<?> createEnumDeserializer(DeserializationContext ctxt,
             JavaType type, BeanDescription beanDesc, BeanProperty property)
         throws JsonMappingException;
 
-    public abstract JsonDeserializer<?> createMapDeserializer(DeserializationConfig config,
+    public abstract JsonDeserializer<?> createMapDeserializer(DeserializationContext ctxt,
             MapType type, BeanDescription beanDesc, BeanProperty property)
         throws JsonMappingException;
 
-    public abstract JsonDeserializer<?> createMapLikeDeserializer(DeserializationConfig config,
+    public abstract JsonDeserializer<?> createMapLikeDeserializer(DeserializationContext ctxt,
             MapLikeType type, BeanDescription beanDesc, BeanProperty property)
         throws JsonMappingException;
 
@@ -265,7 +265,7 @@
      * @return Key deserializer to use for specified type, if one found; null if not
      *   (and default key deserializer should be used)
      */
-    public abstract KeyDeserializer createKeyDeserializer(DeserializationConfig config,
+    public abstract KeyDeserializer createKeyDeserializer(DeserializationContext ctxt,
             JavaType type, BeanProperty property)
         throws JsonMappingException;
     
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/StdDeserializationContext.java b/src/main/java/com/fasterxml/jackson/databind/deser/StdDeserializationContext.java
index 866f1fb..8c29676 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/StdDeserializationContext.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/StdDeserializationContext.java
@@ -7,7 +7,9 @@
 
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.annotation.NoClass;
 import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException;
+import com.fasterxml.jackson.databind.introspect.Annotated;
 import com.fasterxml.jackson.databind.util.ArrayBuilders;
 import com.fasterxml.jackson.databind.util.ClassUtil;
 import com.fasterxml.jackson.databind.util.LinkedNode;
@@ -35,7 +37,7 @@
      */
     protected JsonParser _parser;
 
-    protected final DeserializerCache _deserProvider;
+    protected final DeserializerCache _deserCache;
 
     protected final InjectableValues _injectableValues;
     
@@ -54,11 +56,11 @@
      */
 
     public StdDeserializationContext(DeserializationConfig config, JsonParser jp,
-            DeserializerCache prov, InjectableValues injectableValues)
+            DeserializerCache cache, InjectableValues injectableValues)
     {
     	super(config);
         _parser = jp;
-        _deserProvider = prov;
+        _deserCache = cache;
         _injectableValues = injectableValues;
     }
 
@@ -68,9 +70,8 @@
     /**********************************************************
      */
 
-    @Override
-    public DeserializerCache getDeserializerProvider() {
-        return _deserProvider;
+    public DeserializerCache getDeserializerCache() {
+        return _deserCache;
     }
 
     /**
@@ -103,21 +104,115 @@
     @Override
     public JsonDeserializer<Object> findValueDeserializer(JavaType type,
             BeanProperty property) throws JsonMappingException {
-        return _deserProvider.findValueDeserializer(this, type, property);
+        return _deserCache.findValueDeserializer(this, type, property);
     }
     
     @Override
     public JsonDeserializer<Object> findTypedValueDeserializer(JavaType type,
             BeanProperty property) throws JsonMappingException {
-        return _deserProvider.findTypedValueDeserializer(this, type, property);
+        return _deserCache.findTypedValueDeserializer(this, type, property);
     }
 
     @Override
     public KeyDeserializer findKeyDeserializer(JavaType keyType,
             BeanProperty property) throws JsonMappingException {
-        return _deserProvider.findKeyDeserializer(_config, keyType, property);
+        return _deserCache.findKeyDeserializer(this, keyType, property);
     }
     
+    @SuppressWarnings("unchecked")
+    @Override
+    public JsonDeserializer<Object> deserializerInstance(Annotated annotated,
+            BeanProperty property, Object deserDef)
+        throws JsonMappingException
+    {
+        if (deserDef == null) {
+            return null;
+        }
+        JsonDeserializer<?> deser;
+        
+        if (deserDef instanceof JsonDeserializer) {
+            deser = (JsonDeserializer<?>) deserDef;
+        } else {
+            /* Alas, there's no way to force return type of "either class
+             * X or Y" -- need to throw an exception after the fact
+             */
+            if (!(deserDef instanceof Class)) {
+                throw new IllegalStateException("AnnotationIntrospector returned deserializer definition of type "+deserDef.getClass().getName()+"; expected type JsonDeserializer or Class<JsonDeserializer> instead");
+            }
+            Class<?> deserClass = (Class<?>)deserDef;
+            // there are some known "no class" markers to consider too:
+            if (deserClass == JsonDeserializer.None.class || deserClass == NoClass.class) {
+                return null;
+            }
+            if (!JsonDeserializer.class.isAssignableFrom(deserClass)) {
+                throw new IllegalStateException("AnnotationIntrospector returned Class "+deserClass.getName()+"; expected Class<JsonDeserializer>");
+            }
+            HandlerInstantiator hi = _config.getHandlerInstantiator();
+            if (hi != null) {
+                deser = hi.deserializerInstance(_config, annotated, deserClass);
+            } else {
+                deser = (JsonDeserializer<?>) ClassUtil.createInstance(deserClass,
+                        _config.canOverrideAccessModifiers());
+            }
+        }
+        // First: need to resolve
+        if (deser instanceof ResolvableDeserializer) {
+            ((ResolvableDeserializer) deser).resolve(this);
+        }
+        // Second: contextualize:
+        if (deser instanceof ContextualDeserializer<?>) {
+            deser = ((ContextualDeserializer<?>) deser).createContextual(_config, property);
+        }
+        return (JsonDeserializer<Object>) deser;
+    }
+
+    @Override
+    public KeyDeserializer keyDeserializerInstance(Annotated annotated,
+            BeanProperty property, Object deserDef)
+        throws JsonMappingException
+    {
+        if (deserDef == null) {
+            return null;
+        }
+
+        KeyDeserializer deser;
+        
+        if (deserDef instanceof KeyDeserializer) {
+            deser = (KeyDeserializer) deserDef;
+        } else {
+            if (!(deserDef instanceof Class)) {
+                throw new IllegalStateException("AnnotationIntrospector returned key deserializer definition of type "
+                        +deserDef.getClass().getName()
+                        +"; expected type KeyDeserializer or Class<KeyDeserializer> instead");
+            }
+            Class<?> deserClass = (Class<?>)deserDef;
+            // there are some known "no class" markers to consider too:
+            if (deserClass == KeyDeserializer.None.class || deserClass == NoClass.class) {
+                return null;
+            }
+            if (!KeyDeserializer.class.isAssignableFrom(deserClass)) {
+                throw new IllegalStateException("AnnotationIntrospector returned Class "+deserClass.getName()
+                        +"; expected Class<KeyDeserializer>");
+            }
+            HandlerInstantiator hi = _config.getHandlerInstantiator();
+            if (hi != null) {
+                deser = hi.keyDeserializerInstance(_config, annotated, deserClass);
+            } else {
+                deser = (KeyDeserializer) ClassUtil.createInstance(deserClass,
+                        _config.canOverrideAccessModifiers());
+            }
+        }
+        // First: need to resolve
+        if (deser instanceof ResolvableDeserializer) {
+            ((ResolvableDeserializer) deser).resolve(this);
+        }
+        // Second: contextualize:
+        if (deser instanceof ContextualKeyDeserializer) {
+            deser = ((ContextualKeyDeserializer) deser).createContextual(_config, property);
+        }
+        return deser;
+    }
+
     /*
     /**********************************************************
     /* Public API, helper object recycling
diff --git a/src/test/java/com/fasterxml/jackson/databind/TestHandlerInstantiation.java b/src/test/java/com/fasterxml/jackson/databind/TestHandlerInstantiation.java
index 26aebe6..6d1dd78 100644
--- a/src/test/java/com/fasterxml/jackson/databind/TestHandlerInstantiation.java
+++ b/src/test/java/com/fasterxml/jackson/databind/TestHandlerInstantiation.java
@@ -179,8 +179,9 @@
         }
         
         @Override
-        public JsonDeserializer<?> deserializerInstance(DeserializationConfig config, Annotated annotated,
-                Class<? extends JsonDeserializer<?>> deserClass)
+        public JsonDeserializer<?> deserializerInstance(DeserializationConfig config,
+                Annotated annotated,
+                Class<?> deserClass)
         {
             if (deserClass == MyBeanDeserializer.class) {
                 return new MyBeanDeserializer(_prefix);
@@ -190,7 +191,7 @@
 
         @Override
         public KeyDeserializer keyDeserializerInstance(DeserializationConfig config,
-                Annotated annotated, Class<? extends KeyDeserializer> keyDeserClass)
+                Annotated annotated, Class<?> keyDeserClass)
         {
             if (keyDeserClass == MyKeyDeserializer.class) {
                 return new MyKeyDeserializer();
@@ -211,7 +212,7 @@
 
         @Override
         public TypeIdResolver typeIdResolverInstance(MapperConfig<?> config,
-                Annotated annotated, Class<? extends TypeIdResolver> resolverClass)
+                Annotated annotated, Class<?> resolverClass)
         {
             if (resolverClass == CustomIdResolver.class) {
                 return new CustomIdResolver("!!!");
@@ -221,7 +222,7 @@
 
         @Override
         public TypeResolverBuilder<?> typeResolverBuilderInstance(MapperConfig<?> config, Annotated annotated,
-                Class<? extends TypeResolverBuilder<?>> builderClass)
+                Class<?> builderClass)
         {
             return null;
         }