0

I am stuck in this problem for a while and can not sleep:C

when I use beanPostProcessor to create proxy for a beanA(beanPostProcessor not depend on beanA), proxy works well.But if beanPostProcessor depend on beanA,it not work.And I found beanA is not proxied in Spring ApplicationContext when beanPostProcessor is depend on it

TargetIface:

public interface TargetIface {
    void work();
}

TargetA:

public class TargetA implements TargetIface {
    public void work() {
        System.out.println("targetA is working...");
    }
}

TargetB:

public class TargetB implements TargetIface {
    public void work() {
        System.out.println("targetB is working...");
    }
}

SimpleAdivsor:

public class SimpleAdvisor extends DefaultPointcutAdvisor {

private TargetIface targetIface;

private final Advice advice = new MethodInterceptor() {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("advice intercept....");
        if (invocation.getThis().equals(targetIface)) {
            System.out.println("my advice");
        }
        //no adivce
        return invocation.proceed();
    }
};

public SimpleAdvisor() {
    setAdvice(advice);
}

public void setTargetIface(TargetIface targetIface) {
    this.targetIface = targetIface;
}
}

beanPostProcessor:

public class ProxyProcessor implements BeanPostProcessor {


private List<Advisor> advisors;

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    return bean;
}

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    if (bean instanceof TargetIface) {
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setTarget(bean);
        proxyFactory.addAdvisors(advisors);

        return proxyFactory.getProxy();
    }
    return bean;
}

public void setAdvisors(List<Advisor> advisors) {
    this.advisors = advisors;
}
}

mainClass:

ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/Application-context.xml");
    TargetA targetA = context.getBean(TargetA.class);
    targetA.work();

first case:proxyBeanProcessor not depend on targetA

<bean id="proxyBeanProcessor" class="net.fendar.test.spring.processor.ProxyProcessor">
    <property name="advisors">
        <list>
            <bean class="net.fendar.test.spring.advisor.SimpleAdvisor">
                <!--<property name="targetIface" ref="targetA"/>-->
            </bean>
        </list>
    </property>
</bean>

<bean id="targetA" class="net.fendar.test.spring.bean.TargetA"/>
<bean id="targetB" class="net.fendar.test.spring.bean.TargetB"/>

output:

advice intercept....
targetA is working...

bean in applicationContextenter image description here

second case:proxyBeanProcessor depend on Target,

<bean id="proxyBeanProcessor" class="net.fendar.test.spring.processor.ProxyProcessor">
    <property name="advisors">
        <list>
            <bean class="net.fendar.test.spring.advisor.SimpleAdvisor">
                <property name="targetIface" ref="targetA"/>
            </bean>
        </list>
    </property>
</bean>

<bean id="targetA" class="net.fendar.test.spring.bean.TargetA"/>
<bean id="targetB" class="net.fendar.test.spring.bean.TargetB"/>

<bean id="proxyBeanProcessor" class="net.fendar.test.spring.processor.ProxyProcessor">
    <property name="Target" ref="Target"/>
</bean>

output:

targetA is working...

bean in application:

enter image description here

fendar
  • 21
  • 8

1 Answers1

0

If your BeanPostProcessor bean depends on the bean you want to proxy

<bean id="proxyBeanProcessor" class="net.fendar.test.spring.processor.ProxyProcessor">
    <property name="Target" ref="Target"/>
</bean>

then that bean must necessarily be created before your ProxyProcessor bean is ready. And, if it's not ready, then there's no way it can post process any other beans, including your target bean.


When Spring initializes your beans, it passes them through all registered BeanPostProcessor bean instances. This implies that the BeanPostProcesser beans have already been initialized. Your case demonstrates a scenario where a bean is initialized before a BeanPostProcessor, which therefore can't process it.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • tkx,I have tried to depend on other bean(not target bean) and proxy worked when calling the target.work() method.Only depending on target not works – fendar Jul 22 '16 at 00:37
  • @fendar It's all about the order of initialization here. If your `BeanPostProcessor` was initialized fully before the target, then it **can** post process it. If the `BeanPostProcessor` is not fully initialized because it's depending on the target, then it **cannot** post process it. – Sotirios Delimanolis Jul 22 '16 at 00:40
  • @fendar It's not clear what your problem is. Your `ProxyProcessor` doesn't need the `target` in the example you've shown. – Sotirios Delimanolis Jul 22 '16 at 01:04
  • sry for reply lately,I have edited my question to show the dependency;SimpleAdvisor do advice not on each TargetIface,so SimpleAdvisor needs to know which target should be advised – fendar Jul 22 '16 at 02:43