Hoe gebruik je de Spring FactoryBean?

1. Overzicht

Er zijn twee soorten bonen in de Spring-bonencontainer: gewone bonen en fabrieksbonen. Spring gebruikt de eerste rechtstreeks, terwijl de laatste zelf objecten kan produceren die door het raamwerk worden beheerd.

En, simpel gezegd, we kunnen een fabrieksboon bouwen door te implementeren org.springframework.beans.factory.FactoryBean koppel.

2. De basisprincipes van fabrieksbonen

2.1. Implementeer een FactoryBean

Laten we eens kijken naar de FactoryBean interface eerst:

openbare interface FactoryBean {T getObject () genereert uitzondering; Klasse getObjectType (); boolean isSingleton (); }

Laten we de drie methoden bespreken:

  • getObject () - retourneert een object dat door de fabriek is geproduceerd, en dit is het object dat door Spring container zal worden gebruikt
  • getObjectType () - geeft het type object terug dat dit FactoryBean produceert
  • isSingleton () - geeft aan of het object hierdoor is geproduceerd FactoryBean is een singleton

Laten we nu een voorbeeld implementeren FactoryBean. We implementeren een ToolFactory die objecten van het type produceert Tool:

openbare klasse Tool {privé int id; // standaard constructeurs, getters en setters}

De ToolFactory zelf:

openbare klasse ToolFactory implementeert FactoryBean {private int factoryId; private int toolId; @Override publieke tool getObject () gooit uitzondering {retourneer nieuwe tool (toolId); } @Override public Class getObjectType () {return Tool.class; } @Override openbare boolean isSingleton () {return false; } // standaard setters en getters}

Zoals we kunnen zien, is de ToolFactory is een FactoryBean, die kan produceren Tool voorwerpen.

2.2. Gebruik FactoryBean Met XML-gebaseerde configuratie

Laten we nu eens kijken hoe u onze ToolFactory.

We beginnen met het bouwen van een tool met op XML gebaseerde configuratie - factorybean-spring-ctx.xml:

Vervolgens kunnen we testen of het Tool object is correct geïnjecteerd:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (locations = {"classpath: factorybean-spring-ctx.xml"}) openbare klasse FactoryBeanXmlConfigTest {@Autowired privétooltool; @Test openbare ongeldige testConstructWorkerByXml () {assertThat (tool.getId (), equalTo (1)); }}

Het testresultaat laat zien dat we erin slagen om het gereedschapsobject geproduceerd door de ToolFactory met de eigenschappen die we hebben geconfigureerd in het factorybean-spring-ctx.xml.

Het testresultaat laat ook zien dat de Spring-container het object gebruikt dat door de FactoryBean in plaats van zichzelf voor afhankelijkheidsinjectie.

Hoewel de Spring-container de FactoryBean‘S getObject () de retourwaarde van de methode als de bean, kunt u ook de FactoryBean zelf.

Om toegang te krijgen tot het FactoryBean, u hoeft alleen een "&" toe te voegen voor de boonnaam.

Laten we proberen de fabrieksboon en zijn fabrieks-ID eigendom:

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

2.3. Gebruik FactoryBean Met op Java gebaseerde configuratie

Gebruik FactoryBean met op Java gebaseerde configuratie is een beetje anders met op XML gebaseerde configuratie, je moet de FactoryBean‘S getObject () methode expliciet.

Laten we het voorbeeld in de vorige paragraaf omzetten in een op Java gebaseerd configuratievoorbeeld:

@Configuratie openbare klasse FactoryBeanAppConfig {@Bean (naam = "tool") openbare ToolFactory toolFactory () {ToolFactory factory = nieuwe ToolFactory (); factory.setFactoryId (7070); factory.setToolId (2); terugkeer fabriek; } @Bean public Tool tool () gooit uitzondering {return toolFactory (). GetObject (); }}

Vervolgens testen we of het Tool object is correct geïnjecteerd:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (classes = FactoryBeanAppConfig.class) openbare klasse FactoryBeanJavaConfigTest {@Autowired privétooltool; @Resource (name = "& tool") privé ToolFactory toolFactory; @Test openbare ongeldige testConstructWorkerByJava () {assertThat (tool.getId (), equalTo (2)); assertThat (toolFactory.getFactoryId (), equalTo (7070)); }}

Het testresultaat laat hetzelfde effect zien als de vorige op XML gebaseerde configuratietest.

3. Manieren om te initialiseren

Soms moet u een aantal bewerkingen uitvoeren nadat de FactoryBean is ingesteld maar vóór de getObject () methode wordt aangeroepen, net als eigenschappencontrole.

U kunt dit bereiken door het Initialiseren Bean interface of gebruiken @PostConstruct annotatie.

Meer details over het gebruik van deze twee oplossingen zijn geïntroduceerd in een ander artikel: Gids voor het uitvoeren van logica bij opstarten in het voorjaar.

4. AbstractFactoryBean

De lente biedt de AbstractFactoryBean als een simpele sjabloon superklasse voor FactoryBean implementaties. Met deze basisklasse kunnen we nu gemakkelijker een fabrieksboon implementeren die een singleton of een prototype-object creëert.

Laten we een SingleToolFactory en een NonSingleToolFactory om te laten zien hoe te gebruiken AbstractFactoryBean voor zowel singleton- als prototypetype:

openbare klasse SingleToolFactory breidt AbstractFactoryBean {private int factoryId uit; private int toolId; @Override public Class getObjectType () {return Tool.class; } @Override beschermde Tool createInstance () gooit uitzondering {retourneer nieuwe tool (toolId); } // standaard setters en getters}

En nu de niet-singleton-implementatie:

openbare klasse NonSingleToolFactory breidt AbstractFactoryBean {private int factoryId uit; private int toolId; openbare NonSingleToolFactory () {setSingleton (false); } @Override public Class getObjectType () {return Tool.class; } @Override beschermde Tool createInstance () gooit uitzondering {retourneer nieuwe tool (toolId); } // standaard setters en getters}

Ook de XML-configuratie voor deze fabrieksbonen:

Nu kunnen we testen of het Werknemer De eigenschappen van objecten worden geïnjecteerd zoals we verwachten:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (locations = {"classpath: factorybean-abstract-spring-ctx.xml"}) openbare klasse AbstractFactoryBeanTest {@Resource (name = "singleTool") privé Tool tool1; @Resource (name = "singleTool") privé Tool tool2; @Resource (name = "nonSingleTool") privé Tool tool3; @Resource (name = "nonSingleTool") privé-tool tool4; @Test openbare ongeldige testSingleToolFactory () {assertThat (tool1.getId (), equalTo (1)); assertTrue (tool1 == tool2); } @Test openbare ongeldige testNonSingleToolFactory () {assertThat (tool3.getId (), equalTo (2)); assertThat (tool4.getId (), equalTo (2)); assertTrue (tool3! = tool4); }}

Zoals we kunnen zien aan de hand van de tests, is de SingleToolFactory produceert een singleton-object en de NonSingleToolFactory produceert prototype-object.

Merk op dat het niet nodig is om de singleton-eigenschap in te stellen SingleToolFactory Omdat in AbstractFactory, is de standaardwaarde van de singleton-eigenschap waar.

5. Conclusie

Gebruik maken van een FactoryBean kan een goede gewoonte zijn om complexe constructielogica in te kapselen of om het configureren van zeer configureerbare objecten eenvoudiger te maken in het voorjaar.

Dus in dit artikel hebben we de basisprincipes geïntroduceerd voor het implementeren van onze FactoryBean, hoe het te gebruiken in zowel op XML gebaseerde configuratie als op Java gebaseerde configuratie, en enkele andere diverse aspecten van FactoryBean, zoals initialisatie van FactoryBean en AbstractFactoryBean.

Zoals altijd staat de volledige bron op GitHub.