Announcement Announcement Module
Collapse
No announcement yet.
Abstract Schema Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Abstract Schema

    As part of a project to get a better understanding of how to use CGLIB I've been creating an implementation of Rickard Öberg's "abstract schema" approach to AOP introduction and interception targeted for Spring's AOP subsystem. I've managed to get everything working nicely if I programmatically create my proxies using ProxyFactory however I've run into a small problem with creating proxies using an application context.

    With "abstract schema" the target class declares it requires a specific introduction by declaring that it implements a particular interface but then *not* actually implementing any of the interface's methods. For example the following class requires that an implementation for the interfaces Foo and Bar be provided by the AOP system

    Code:
    public abstract class SomeClass
    implements Foo,Bar
    {
    public String someMethod() {..}
    }
    I would like to be able to configure the introductions for this class in an application context using some config along these lines:

    Code:
    <beans>  
        <bean id="someClass" class="SomeClass" />
    
        <bean id="autoProxyCreator"
            class="...DefaultAdvisorAutoProxyCreator">
        </bean>
    
        <bean id="fooImpl" class="FooImpl" />
        <bean id="fooIntroduction 
                class="...DelegatingIntroductionInterceptor">
            <constructor-arg><ref local="fooImpl"/</constructor-arg>	
        </bean>
    
        <bean id="barImpl" class="BarImpl" />
        <bean id="barIntroduction 
                class="...DelegatingIntroductionInterceptor">
            <constructor-arg><ref local="BarImpl"/</constructor-arg>	
        </bean>
    </beans>
    However as "SomeClass" is abstract the bean factory is unable to instantiate it.

    So how do I instantiate this class? My first thought was to use a BeanFactoryPostProcessor that would find the bean definition for the abstract class, generate a new concrete subclass and replace the abstract class with this new subclass.

    Code:
        public void postProcessBeanFactory&#40;
                ConfigurableListableBeanFactory beanFactoryToProcess&#41;
                throws BeansException &#123;
            String&#91;&#93; beanNames = beanFactoryToProcess.getBeanDefinitionNames&#40;&#41;;
            for &#40;int i = 0; i < beanNames.length; i++&#41; &#123;
                BeanDefinition bd = beanFactoryToProcess
                        .getBeanDefinition&#40;beanNames&#91;i&#93;&#41;;
                Class beanType = beanFactoryToProcess.getType&#40;beanNames&#91;i&#93;&#41;;
                if &#40;Modifier.isAbstract&#40;beanType.getModifiers&#40;&#41;&#41;&#41; &#123;
                    &#40;&#40;AbstractBeanDefinition&#41;bd&#41;.setBeanClass&#40;createContreteClass&#40;beanType&#41;&#41;;
                &#125;
            &#125;
        &#125;
        
        private Class createContreteClass&#40;Class abstractClass&#41; &#123;
            ...
        &#125;
    Unfortunately as I am generating the concrete subclass using a CGLIB enhancer I must use the Enhancer.create() method to create the instance so that the callbacks are correctly installed....

    What about using my BeanFactoryPostProcessor to install a new InstantiationStrategy into the bean factory? Unfortunately the instantiationStrategy property on AbstractAutowireCapableBeanFactory is protected so I can't access it... As a stop gap measure I've resorted to setting the InstantiationStrategy using reflection.

    Does anyone have a suggestion of how I can get around this? My first thought was that setInstantiationStrategy could be made public and moved over to ConfigurableBeanFactory but I assume there are strong reason this was not done when this interface was created.

    Thanks,

    Ollie

    PS. If anyone's interested here's the programmatic configuration for this problem

    Code:
        SomeClass someClassTarget = &#40;SomeClass&#41; new MethodReplaceableSubclassCreator&#40;
                    SomeClass.class, AbstractMethodMatcher.INSTANCE&#41;
    		.instantiate&#40;null, null&#41;;
        &#40;&#40;MethodReplaceable&#41;someClassTarget&#41;
                    .setMethodReplacer&#40;CurrentAopProxyMethodReplacer.INSTANCE&#41;;
    
        ProxyFactory pf = new ProxyFactory&#40;someClassTarget&#41;;
        pf.setExposeProxy&#40;true&#41;;
        pf.setProxyTargetClass&#40;true&#41;;
        pf.addAdvice&#40;new DelegatingIntroductionInterceptor&#40;
                            new FooImpl&#40;&#41;&#41;&#41;;
        pf.addAdvice&#40;new DelegatingIntroductionInterceptor&#40;
                            new BarImpl&#40;&#41;&#41;&#41;;
        SomeClass someClass = &#40;SomeClass&#41;pf.getProxy&#40;&#41;
    
        someClass.foo&#40;&#41;;
        ...

  • #2
    Oliver,

    I've got an almost complete implementation of abstract schema, intended for Spring 1.2, but not in the sandbox yet, as I haven't had time to address all issues.

    It might be best if we take this offline--send me a private message and we can compare notes. I would like to see your implementation. In my implementation, the abstract schema subclass is generated by an advice factory, so there don't need to be any changes to the IoC container.

    R

    Comment

    Working...
    X