是否可以动态创建一个对象(Spring Bean)?这样可以选择要在运行时选择要使用的实现。在编译时你不知道究竟应该创建什么对象。应用程序应根据属性文件确定要创建的对象。
1.我们创建一个注释,这样就可以标记应该能够动态创建对象的方法:
package your.package;
@Retention(RetentionPolicy.RUNTIME) public @interface InjectDynamicObject { }
|
2. 在方法中使用新创建的注释,该注释应该能够动态创建对象:
@Service
public class CustomerServiceImpl { private Customer dynamicCustomerWithAspect; @InjectDynamicObject public Customer getDynamicCustomerWithAspect() { return this.dynamicCustomerWithAspect; } }
|
3. 使用Pointcut和Advise编写面向方面编程AOP的一个方面,更改步骤2中方法返回的对象:
@Component @Aspect public class DynamicObjectAspect { // This comes from the property file @Value("${dynamic.object.name}") private String object; @Autowired private ApplicationContext applicationContext; @Pointcut("execution(@com.lofi.springbean.dynamic. InjectDynamicObject * *(..))") public void beanAnnotatedWithInjectDynamicObject() { } @Around("beanAnnotatedWithInjectDynamicObject()") public Object adviceBeanAnnotatedWithInjectDynamicObject( ProceedingJoinPoint pjp) throws Throwable { pjp.proceed(); // Create the bean or object depends on the property file Object createdObject = applicationContext.getBean(object); return createdObject; } }
|
4.编写从@InjectDynamicObject返回的你自己的类。名称在属性文件中配置。在这个例子中,我写了两个不同的Customer实现:CustomerOneImpl和CustomerTwoImpl:
@Component("customerOne") public class CustomerOneImpl implements Customer { @Override public String getName() { return "Customer One"; } } application.properties dynamic.object.name=customerOne
|
5.编写单元测试的测试方法:
@RunWith(SpringRunner.class) @SpringBootTest public class CustomerServiceImplTest { @Autowired private CustomerServiceImpl customerService; @Test public void testGetDynamicCustomerWithAspect() { // Dynamic object creation logger.info("Dynamic Customer with Aspect: " + customerService.getDynamicCustomerWithAspect() .getName()); }
|
好的,有另一种更简单的方法可以做到这一点 没有Aspects和AspectJ,只需要纯粹的Spring:
无AOP
只需将所有组件实现注入Map中,然后从中获取正确的实现。就像我们在eXTra客户端应用程序中所做的一样。请以我们的PluginsLocatorManager实现为例。Spring将Bean的Bean名称作为String注入,而Bean本身则自动注入。
“......只要预期的键类型为String,即使是键入的Map也可以自动装配。Map值将包含所需类型的所有bean,并且键将包含相应的bean名称“ (有关详细信息,请参阅Spring文档)。
@Service public class CustomerServiceImpl { // We inject the customer implementations into a Map @Autowired private Map<String, Customer> dynamicCustomerWithMap; // This comes from the property file as a key for the Map @Value("${dynamic.object.name}") private String object; public Customer getDynamicCustomerWithMap() { return this.dynamicCustomerWithMap.get(object); } }
|
Github