Hvordan bruges Spring FactoryBean?

1. Oversigt

Der er to slags bønner i Spring bønnebeholderen: almindelige bønner og fabriksbønner. Spring bruger førstnævnte direkte, mens sidstnævnte selv kan producere objekter, der styres af rammen.

Og enkelt sagt kan vi bygge en fabriksbønne ved at implementere den org.springframework.beans.factory.FactoryBean interface.

2. Grundlæggende om fabriksbønner

2.1. Implementere a FactoryBean

Lad os se på FactoryBean interface først:

offentlig grænseflade FactoryBean {T getObject () kaster undtagelse; Klasse getObjectType (); boolsk isSingleton (); }

Lad os diskutere de tre metoder:

  • getObject () - returnerer et objekt, der er produceret af fabrikken, og dette er det objekt, der skal bruges af Spring container
  • getObjectType () - returnerer den type objekt, som dette FactoryBean producerer
  • isSingleton () - angiver, om det objekt, der produceres af dette FactoryBean er en singleton

Lad os nu implementere et eksempel FactoryBean. Vi implementerer en ToolFactory der producerer genstande af typen Værktøj:

public class Tool {privat int id; // standardkonstruktører, getters og settere}

Det ToolFactory sig selv:

offentlig klasse ToolFactory implementerer FactoryBean {private int factoryId; private int toolId; @Override public Tool getObject () kaster undtagelse {returner nyt værktøj (toolId); } @ Override public Class getObjectType () {return Tool.class; } @ Override offentlig boolsk isSingleton () {returner falsk; } // standard settere og getters}

Som vi kan se, er ToolFactory er en FactoryBean, som kan producere Værktøj genstande.

2.2. Brug FactoryBean Med XML-baseret konfiguration

Lad os nu se på, hvordan vi bruger vores ToolFactory.

Vi begynder at konstruere et værktøj med XML-baseret konfiguration - factorybean-spring-ctx.xml:

Dernæst kan vi teste om Værktøj genstand indsprøjtes korrekt:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (locations = {"classpath: factorybean-spring-ctx.xml"}) offentlig klasse FactoryBeanXmlConfigTest {@Autowired private Tool tool; @Test offentlig ugyldig testConstructWorkerByXml () {assertThat (tool.getId (), equalTo (1)); }}

Testresultatet viser, at det lykkes os at indsprøjte det værktøjsobjekt, der produceres af ToolFactory med de egenskaber, vi konfigurerede i factorybean-spring-ctx.xml.

Testresultatet viser også, at fjederbeholderen bruger det objekt, der produceres af FactoryBean i stedet for sig selv til afhængighedsinjektion.

Selvom Spring Container bruger FactoryBean'S getObject () metodens returværdi som bønnen, kan du også bruge FactoryBean sig selv.

For at få adgang til FactoryBean, skal du bare tilføje et "&" før bønnenavnet.

Lad os prøve at få fabriksbønnen og dens fabrikId ejendom:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (locations = {"classpath: factorybean-spring-ctx.xml"}) offentlig klasse FactoryBeanXmlConfigTest {@Resource (name = "& tool") privat ToolFactory toolFactory; @Test offentlig ugyldig testConstructWorkerByXml () {assertThat (toolFactory.getFactoryId (), equalTo (9090)); }}

2.3. Brug FactoryBean Med Java-baseret konfiguration

Brug FactoryBean med Java-baseret konfiguration er lidt anderledes med XML-baseret konfiguration, skal du ringe til FactoryBean'S getObject () metode eksplicit.

Lad os konvertere eksemplet i det forrige afsnit til et Java-baseret konfigurationseksempel:

@Configuration offentlig klasse FactoryBeanAppConfig {@Bean (name = "tool") offentlig ToolFactory toolFactory () {ToolFactory fabrik = ny ToolFactory (); factory.setFactoryId (7070); factory.setToolId (2); retur fabrik; } @Bean offentlige værktøjsværktøj () kaster undtagelse {return toolFactory (). GetObject (); }}

Derefter tester vi, om Værktøj genstand indsprøjtes korrekt:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (klasser = FactoryBeanAppConfig.class) offentlig klasse FactoryBeanJavaConfigTest {@Autowired private Tool tool; @Resource (name = "& tool") privat ToolFactory toolFactory; @Test offentlig ugyldighed testConstructWorkerByJava () {assertThat (tool.getId (), equalTo (2)); assertThat (toolFactory.getFactoryId (), equalTo (7070)); }}

Testresultatet viser den samme effekt som den tidligere XML-baserede konfigurationstest.

3. Måder at initialisere

Nogle gange er du nødt til at udføre nogle operationer efter FactoryBean er indstillet, men før getObject () metode kaldes, som egenskabskontrol.

Du kan opnå dette ved at implementere InitialisererBønne interface eller brug @PostConstruct kommentar.

Flere detaljer om brugen af ​​disse to løsninger er blevet introduceret i en anden artikel: Guide til at køre logik ved opstart om foråret.

4. AbstraktFabrikBønne

Foråret giver AbstraktFabrikBønne som en simpel skabelonsuperklasse til FactoryBean implementeringer. Med denne basisklasse kan vi nu mere bekvemt implementere en fabriksbønne, der skaber en singleton eller en prototype-genstand.

Lad os implementere en SingleToolFactory og en NonSingleToolFactory for at vise, hvordan man bruger AbstraktFabrikBønne til både singleton og prototypetype:

offentlig klasse SingleToolFactory udvider AbstractFactoryBean {private int factoryId; private int toolId; @Override public Class getObjectType () {return Tool.class; } @ Override-beskyttet værktøj createInstance () kaster undtagelse {returner nyt værktøj (toolId); } // standard settere og getters}

Og nu implementeringen af ​​nonsingleton:

offentlig klasse NonSingleToolFactory udvider AbstractFactoryBean {private int fabrikId; private int toolId; public NonSingleToolFactory () {setSingleton (false); } @ Override public Class getObjectType () {return Tool.class; } @ Override-beskyttet værktøj createInstance () kaster undtagelse {returner nyt værktøj (toolId); } // standard settere og getters}

XML-konfigurationen for disse fabriksbønner:

Nu kan vi teste om Arbejder objekters egenskaber injiceres som vi forventer:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (locations = {"classpath: factorybean-abstract-spring-ctx.xml"}) offentlig klasse AbstractFactoryBeanTest {@Resource (name = "singleTool") privat værktøjsværktøj1; @Resource (name = "singleTool") privat værktøjsværktøj2; @Resource (name = "nonSingleTool") privat værktøjsværktøj3; @Resource (name = "nonSingleTool") privat værktøjsværktøj4; @Test offentlig ugyldighed testSingleToolFactory () {assertThat (tool1.getId (), equalTo (1)); assertTrue (værktøj1 == værktøj2); } @Test offentlig ugyldig testNonSingleToolFactory () {assertThat (tool3.getId (), equalTo (2)); assertThat (tool4.getId (), equalTo (2)); assertTrue (tool3! = tool4); }}

Som vi kan se af testene, er SingleToolFactory producerer singleton objekt, og NonSingleToolFactory producerer prototype objekt.

Bemærk, at der ikke er behov for at indstille singleton-ejendom i SingleToolFactory fordi, i AbstraktFabrik, standardværdien for singleton-ejendom er rigtigt.

5. Konklusion

Brug af en FactoryBean kan være en god praksis at indkapsle kompleks konstruktionslogik eller gøre det lettere at konfigurere objekter, der er meget konfigurerbare, om foråret.

Så i denne artikel introducerede vi det grundlæggende om, hvordan vi implementerer vores FactoryBean, hvordan man bruger det i både XML-baseret konfiguration og Java-baseret konfiguration, og nogle andre diverse aspekter af FactoryBean, såsom initialisering af FactoryBean og AbstraktFabrikBønne.

Som altid er den komplette kilde forbi på GitHub.