2009-07-13 8 views
3

Ich habe viele Cookie-Cutter Spring Beans und möchte nicht explizit jede in xml definieren. Also ging ich die Komponenten-Scan-Route, die mir dies ermöglicht. Das ist nett, aber ich habe gerade gemerkt, dass MyBeanPostProcessor nicht für die Beans aufgerufen wird, die mit der Component-Scan-Technik geladen werden. MyBeanPostProcessor versucht einfach, eine Setter-Injektion für diese Beans durchzuführen. Die folgende Konfiguration zeigt nur diesen Ansatz, den ich versuchte, der nicht funktioniert. Irgendwelche anderen Ideen, wie man Einspritzung auf diese Bohnen einstellt?Spring BeanpostProzessor funktioniert nicht bei Component-Scan?

Ich verwende Frühling 2.5.5

Danke, Ben

<context:component-scan base-package="us.benanderson" 
     use-default-filters="false" 
     annotation-config="false" 
     scope-resolver="us.benanderson.MyScopeResolver" 
     name-generator="us.benanderson.MyBeanNameGenerator"> 
    <context:include-filter type="custom" expression="us.benanderson.MyTypeFilter" /> 
</context:component-scan> 
<bean class="us.benanderson.MyBeanPostProcessor"> 
    <property name="order" value="500" /> 
</bean> 
+0

Was passiert, wenn Sie versuchen, eine Bean-Definition explizit hinzuzufügen, statt die Klassenpfadprüfung zu verwenden? Können Sie bestätigen, dass der Postprozessor in diesem Fall funktioniert? – skaffman

+0

Ja, ich habe bestätigt, dass der Beanpostprozessor in diesem Fall funktioniert – andersonbd1

+0

suchen Sie nach Alternativen zum BeanPostProcessor für die Injektion? Oder ist Ihr primäres Ziel, den Component-Scan mit oder ohne BeanPostProcessor arbeiten zu lassen? –

Antwort

5

Hier ist mein Testfall, der scheint zu funktionieren (Frühling 2.5.6). Ich habe darüber nachgedacht, einige Dateien aus Platzgründen auszublenden, aber ich habe mich dagegen entschieden.

Start.java (Einstiegspunkt)

package se.waxwing.test; 

import org.springframework.context.ApplicationContext; 
import org.springframework.context.support.ClassPathXmlApplicationContext; 

public class Start { 
    public static void main(String[] args) { 
     ApplicationContext context = new ClassPathXmlApplicationContext("se/waxwing/test/Context.xml"); 
     context.getBean("customBean"); 
    } 
} 

context.xml

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 
         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> 


    <context:component-scan base-package="se.waxwing.test" 
     use-default-filters="false" 
     annotation-config="false" 
     scope-resolver="se.waxwing.test.MyScopeResolver"> 
     <context:include-filter type="custom" expression="se.waxwing.test.MyTypeFilter" /> 
    </context:component-scan> 

    <bean id="beanProcessor" class="se.waxwing.test.MyBeanPostProcessor" /> 

</beans> 

CustomBean.java (dies ist die möchte ich finden - siehe MyTypeFilter)

package se.waxwing.test; 

public class CustomBean { 

    public CustomBean() { 
     System.err.println("instantiating component"); 
    } 
} 

MyBeanPostProcessor.java

package se.waxwing.test; 

import org.springframework.beans.BeansException; 
import org.springframework.beans.factory.config.BeanPostProcessor; 

public class MyBeanPostProcessor implements BeanPostProcessor { 

    public MyBeanPostProcessor() { 
    } 

    @Override 
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { 
     System.err.println("after " + beanName); 
     return bean; 
    } 

    @Override 
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { 
     System.err.println("before " + beanName); 
     return bean; 
    } 
} 

MyScopeResolver.java

package se.waxwing.test; 

import org.springframework.beans.factory.config.BeanDefinition; 
import org.springframework.context.annotation.ScopeMetadata; 
import org.springframework.context.annotation.ScopeMetadataResolver; 
import org.springframework.context.annotation.ScopedProxyMode; 

public class MyScopeResolver implements ScopeMetadataResolver { 

    @Override 
    public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) { 
     ScopeMetadata result = new ScopeMetadata(); 
     result.setScopedProxyMode(ScopedProxyMode.NO); 
     result.setScopeName("prototype"); 
     return result; 
    } 

} 

MyTypeFilter.java

package se.waxwing.test; 

import java.io.IOException; 

import org.springframework.core.type.classreading.MetadataReader; 
import org.springframework.core.type.classreading.MetadataReaderFactory; 
import org.springframework.core.type.filter.TypeFilter; 

public class MyTypeFilter implements TypeFilter { 

    @Override 
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { 
     return metadataReader.getClassMetadata().getClassName().equals(CustomBean.class.getCanonicalName()); 
    } 
} 

Dies erzeugt die folgende Ausgabe:

 
2009-aug-26 15:44:02 org.springframework.context.support.AbstractApplicationContext prepareRefresh 
INFO: Refreshing org[email protected]c1b531: display name [org[email protected]c1b531]; startup date [Wed Aug 26 15:44:02 CEST 2009]; root of context hierarchy 
2009-aug-26 15:44:02 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 
INFO: Loading XML bean definitions from class path resource [se/waxwing/test/Context.xml] 
2009-aug-26 15:44:02 org.springframework.context.support.AbstractApplicationContext obtainFreshBeanFactory 
INFO: Bean factory for application context [org[email protected]c1b531]: org.s[email protected]121f1d 
2009-aug-26 15:44:02 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons 
INFO: Pre-instantiating singletons in org.s[email protected]121f1d: defining beans [customBean,beanProcessor]; root of factory hierarchy 
instantiating component 
before customBean 
after customBean 

So, wie Sie gefunden sehen können, wurde die customBean Bean Mein Typ Filter, als Bean hinzugefügt, und wenn applicationContext.getBean("customBean") aufgerufen wurde, wurde ein neues Objekt instan tiated und dann wurde es an meinen Post-Bean-Prozessor übergeben.

+0

Ich bin ein Idiot! Nachdem ich Frühling 2.5.6 heruntergeladen und ausprobiert habe (und es war immer noch kaputt), bemerkte ich die Tatsache, dass ich nicht applicationContext.getBean ("customBean") anrief! Es funktionierte also für mich die ganze Zeit - nur meine Art zu bestätigen war gebrochen! Vielen Dank für die Übermittlung Ihres Codes und die Bestätigung, dass er funktioniert. Ich möchte dir das Kopfgeld geben, aber ich weiß nicht wie. Es gibt kein Kontrollkästchen oder irgendetwas - entsprechend: http://meta.stackexchange.com/questions/13421/cant-accept-answer-for-boundied-question-on-serverfault Ich denke, du bist kein Glück ? – andersonbd1

+0

Kein Problem, es hat mich dazu gebracht, mit benutzerdefinierten Scope-Resolvern und Type-Filtern herumzuspielen, was eine gute Sache ist. Ich glaube, ich habe kein Glück auf dieser Prämie - kann das System nicht bekämpfen. :) – waxwing

-1

Nach dem Anwendungskontext hat Prüfung geladen, dass die Bohnen, die Sie kommentierten haben zur Verfügung stehen.

Ich vermute, seit Sie "annotation-config" ausgeschaltet haben, ignoriert es Ihre Anmerkungen.

+0

Ja, ich habe überprüft, dass die Beans verfügbar sind. Ich habe meinen eigenen Filter geschrieben, weshalb ich annotation-config abgeschaltet habe. – andersonbd1

Verwandte Themen