Smart implementation of strategy mode with Spring auto-injection

1. Background In the course of your work, you...
1. Background

In the course of your work, you sometimes need to perform different logic based on different enumerations (constants).

For example, different user types have different methods of handling, the interface is Handler, and the sample code is as follows:

public interface Handler { void someThing(); }

Some students choose to define a Map <String, Handler>type2BeanMap in the Bean, then use xml to inject constants and corresponding beans.

<bean id="someService"> <property name="type2BeanMap"> <map> <entry key="Vip" value-ref="vipHandler"></entry> <entry key="Common" value-ref="commonHandler"></entry> </map> </property> </bean>

Once you get the user type (vip or common), you can get the corresponding processing bean s to execute through the map.

Doing so will result in a new policy requiring modifications to the xml configuration of the currently injected beans.

If a new superVip type is added

<bean id="someService"> <property name="type2BeanMap"> <map> <entry key="Vip" value-ref="vipHandler"></entry> <entry key="Common" value-ref="commonHandler"></entry> <entry key="SuperVip" value-ref="superVipHandler"></entry> </map> </property> </bean>

So is there a better solution?

2. Solution

A new method has been added to the Handler interface to distinguish between different user types.

public interface Handler { String getType(); void someThing(); }

Each subclass gives its own type that it can handle, such as:

import org.springframework.stereotype.Component; @Component public class VipHandler implements Handler{ @Override public String getType() { return "Vip"; } @Override public void someThing() { System.out.println("Vip User, logic here"); } }

Ordinary users:

@Component public class CommonHandler implements Handler{ @Override public String getType() { return "Common"; } @Override public void someThing() { System.out.println("Ordinary users, logic here"); } }

Then automatically inject the bean List of the target type where it is used to construct the type-to-bean mapping after initialization:

import javax.annotation.PostConstruct; import java.util.List; import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; @Service public class DemoService { @Autowired private List<Handler> handlers; private Map<String, Handler> type2HandlerMap; @PostConstruct public void init(){ type2HandlerMap= handlers.stream().collect(Collectors.toMap(Handler::getType, Function.identity())); } public void test(){ String type ="Vip"; type2HandlerMap.get(type).someThing(); } }

At this point, Spring automatically injects all bean s of Handler type into List <VipHandler> handlers.

The init method then constructs the type-to-bean mapping after the dependency injection is complete. (You can also write some of the above init logic in the afterPropertiesSet method by implementing the InitializingBean interface.
)

When executing business logic, you can get the corresponding bean execution directly based on the type.

Test class:

public class AnnotationConfigApplication { public static void main(String[] args) throws Exception { ApplicationContext ctx = new AnnotationConfigApplicationContext(QuickstartConfiguration.class); DemoService demoService = ctx.getBean(DemoService.class); demoService.test(); } }

Run result:

Vip user, logic to go here

Of course, the return value of getType here can also be directly defined as the enumeration type, where the key is the corresponding enumeration when constructing the Map type to the bean.

Note: If the same type can have multiple processors, you need to define it as private Map < String, List <>Handler > type2HandlersMap and construct it in the init method. Sample code:

@Service public class DemoService { @Autowired private List<Handler> handlers; private Map<String, List<Handler>> type2HandlersMap; @PostConstruct public void init(){ type2HandlersMap= handlers.stream().collect(Collectors.groupingBy(Handler::getType)); } public void test(){ String type ="Vip"; for(Handler handler : type2HandlersMap.get(type)){ handler.someThing();; } } }

In the actual development, it can be used flexibly according to the actual situation.

3. Summary

This paper briefly introduces a method to implement the policy mode through Spring auto-injection.
Avoid adding a new bean with one more modification.
It is very friendly to the students who are writing new processing classes.

11 November 2021, 11:36 | Views: 1951

Add new comment

For adding a comment, please log in
or create account

0 comments