Search in sources :

Example 1 with ObjectFactory

use of org.mule.runtime.dsl.api.component.ObjectFactory in project mule by mulesoft.

the class ObjectFactoryClassRepositoryTestCase method cacheEnableForCGLib.

@Test
public void cacheEnableForCGLib() throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
    Class<ObjectFactory> objectFactoryClass = getObjectFactoryClass();
    // First we create the objectFactory that will create an Enhancer with the callback registered and using internal cache
    ObjectFactory objectFactory = objectFactoryClass.newInstance();
    assertThat(((SmartFactoryBean) objectFactory).isSingleton(), is(true));
    Class firstProxyGenerated = objectFactory.getClass();
    objectFactoryClass = getObjectFactoryClass();
    objectFactory = objectFactoryClass.newInstance();
    assertThat(((SmartFactoryBean) objectFactory).isSingleton(), is(true));
    assertThat(firstProxyGenerated, sameInstance(objectFactory.getClass()));
}
Also used : ObjectFactory(org.mule.runtime.dsl.api.component.ObjectFactory) Test(org.junit.Test)

Example 2 with ObjectFactory

use of org.mule.runtime.dsl.api.component.ObjectFactory in project mule by mulesoft.

the class ObjectFactoryClassRepository method getObjectFactoryDynamicClass.

private Class<ObjectFactory> getObjectFactoryDynamicClass(final ComponentBuildingDefinition componentBuildingDefinition, final Class objectFactoryType, final Class createdObjectType, final Supplier<Boolean> isLazyInitFunction, final Optional<Consumer<Object>> instancePostCreationFunction) {
    /*
     * We need this to allow spring create the object using a FactoryBean but using the object factory setters and getters so we
     * create as FactoryBean a dynamic class that will have the same attributes and methods as the ObjectFactory that the user
     * defined. This way our API does not expose spring specific classes.
     */
    Enhancer enhancer = new Enhancer();
    // Use SmartFactoryBean since it's the only way to force spring to pre-instantiate FactoryBean for singletons
    enhancer.setInterfaces(new Class[] { SmartFactoryBean.class });
    enhancer.setSuperclass(objectFactoryType);
    enhancer.setCallbackType(MethodInterceptor.class);
    if (SmartFactoryBean.class.getClassLoader() != objectFactoryType.getClassLoader()) {
        // CGLIB needs access to both the spring interface and the extended factory class.
        // If the factory class is defined in a plugin, its classloader has to be passed.
        enhancer.setClassLoader(new CompositeClassLoader(ObjectFactoryClassRepository.class.getClassLoader(), objectFactoryType.getClassLoader()));
    }
    // The use of the CGLIB cache is turned off when a post creation function is passed as argument in order to
    // enrich the created proxy with properties. This is only to enable injecting properties in components
    // from the compatibility module.
    // Setting this to false will generate an excessive amount of different proxy classes loaded by the container CL
    // that will end up in Metaspace OOM.
    enhancer.setUseCache(!instancePostCreationFunction.isPresent());
    Class<ObjectFactory> factoryBeanClass = enhancer.createClass();
    registerStaticCallbacks(factoryBeanClass, new Callback[] { (MethodInterceptor) (obj, method, args, proxy) -> {
        final boolean eager = !isLazyInitFunction.get();
        if (method.getName().equals("isSingleton")) {
            return !componentBuildingDefinition.isPrototype();
        }
        if (method.getName().equals("getObjectType") && !ObjectTypeProvider.class.isAssignableFrom(obj.getClass())) {
            return createdObjectType;
        }
        if (method.getName().equals("getObject")) {
            Object createdInstance = proxy.invokeSuper(obj, args);
            instancePostCreationFunction.ifPresent(consumer -> consumer.accept(createdInstance));
            return createdInstance;
        }
        if (method.getName().equals("isPrototype")) {
            return componentBuildingDefinition.isPrototype();
        }
        if (method.getName().equals("isEagerInit")) {
            return eager;
        }
        return proxy.invokeSuper(obj, args);
    } });
    return factoryBeanClass;
}
Also used : MethodInterceptor(org.springframework.cglib.proxy.MethodInterceptor) Consumer(java.util.function.Consumer) Enhancer(org.springframework.cglib.proxy.Enhancer) ComponentBuildingDefinition(org.mule.runtime.dsl.api.component.ComponentBuildingDefinition) Enhancer.registerStaticCallbacks(org.springframework.cglib.proxy.Enhancer.registerStaticCallbacks) CompositeClassLoader(org.mule.runtime.core.internal.util.CompositeClassLoader) Callback(org.springframework.cglib.proxy.Callback) SmartFactoryBean(org.springframework.beans.factory.SmartFactoryBean) Optional(java.util.Optional) ObjectFactory(org.mule.runtime.dsl.api.component.ObjectFactory) Supplier(java.util.function.Supplier) ObjectTypeProvider(org.mule.runtime.dsl.api.component.ObjectTypeProvider) ObjectTypeProvider(org.mule.runtime.dsl.api.component.ObjectTypeProvider) Enhancer(org.springframework.cglib.proxy.Enhancer) ObjectFactory(org.mule.runtime.dsl.api.component.ObjectFactory) SmartFactoryBean(org.springframework.beans.factory.SmartFactoryBean) CompositeClassLoader(org.mule.runtime.core.internal.util.CompositeClassLoader)

Aggregations

ObjectFactory (org.mule.runtime.dsl.api.component.ObjectFactory)2 Optional (java.util.Optional)1 Consumer (java.util.function.Consumer)1 Supplier (java.util.function.Supplier)1 Test (org.junit.Test)1 CompositeClassLoader (org.mule.runtime.core.internal.util.CompositeClassLoader)1 ComponentBuildingDefinition (org.mule.runtime.dsl.api.component.ComponentBuildingDefinition)1 ObjectTypeProvider (org.mule.runtime.dsl.api.component.ObjectTypeProvider)1 SmartFactoryBean (org.springframework.beans.factory.SmartFactoryBean)1 Callback (org.springframework.cglib.proxy.Callback)1 Enhancer (org.springframework.cglib.proxy.Enhancer)1 Enhancer.registerStaticCallbacks (org.springframework.cglib.proxy.Enhancer.registerStaticCallbacks)1 MethodInterceptor (org.springframework.cglib.proxy.MethodInterceptor)1