How do I use the chain of Responsibility design pattern in Spring

The author’s writing skill is still shallow, if there is something wrong, please point out generously, will be grateful

This article is not about designing a responsibility chain in Spring source code, but how to design your own responsibility chain in Spring and how to invoke it.

As one of our commonly used design patterns, the chain of responsibility design pattern has a wide range of uses. For example, we can use the chain of responsibility design pattern to carry out design requirements in some process execution or some dynamic interception, so that our projects will be very good in both availability and scalability.

We do not know about the chain of responsibility can see my previous blog design mode – chain of responsibility mode

How to define a chain

In Java development, if we want to define a chain ourselves, it is very easy to define an abstract class, define a few implementation methods, and set its next property, but in Spring how to combine the framework with our chain? There are three annotations @Component, @Order, and @postconstruct.

  • @Component: Turn our subclasses over to Spring to manage
  • @Order: Define the order of our chain
  • @PostConstruct: The program links us together when it starts

Let’s look at the code directly, first at the abstract class, in fact, responsibility chain abstract class is basically the same.

 1public abstract class PrintChainPattern {

2

3    private PrintChainPattern next;

4

5    public final void print(a) {

6        String message = getMessage();

7

8        log.info("{}, {}",message,message);

9        if(getNext()! =null) {

10            getNext().print();

11        }

12    }

13    public abstract String getMessage(a);

14}

Copy the code

Then we look at the implementation class, followed by four implementation classes, which return two, three, and four. The @order annotation is numbered in ascending Order. Only the code for the first implementation class is shown here.

1@Order(1)

2@Component

3public class OnePrintChainPattern extends PrintChainPattern{

4    @Override

5    public String getMessage(a) {

6        return "one";

7    }

8}

Copy the code

Now, how do we use Spring to assemble our chains

 1@Configuration

2public class InitPrintChainPattern {

3

4    @Autowired

5    private List<PrintChainPattern> printChainPatterns;

6

7    @PostConstruct

8    private void initPrintChainPattern()
{

9        Collections.sort(printChainPatterns, AnnotationAwareOrderComparator.INSTANCE);

10

11        int size = printChainPatterns.size();

12        for (int i = 0; i < size; i++) {

13            if (i == size- 1) {

14                printChainPatterns.get(i).setNext(null);

15            }else {

16                printChainPatterns.get(i).setNext(printChainPatterns.get(i+1));

17            }

18        }

19    }

20

21    public void print(int index){

22        printChainPatterns.get(index- 1).print();

23    }

24}

Copy the code

So here we can see that in the @postconstruct method we’re doing two things

  1. willListAccording to the in@OrderSort the numbers of annotations
  2. Set the next value for each node in turn

So we’ve got this chain together. This chain can then be manipulated arbitrarily, as in my print() method below, which executes from different nodes depending on the value passed in.

How do I use @Autowired in an abstract class

We have combined our chains above, but if all of our subclasses have some classes in common, then that class should be in the abstract class. So what if we want to get this class out of the Spring container?

For example, we have the following class that Spring manages, and all of our subclasses use this class.

1@Bean

2public User setUser(){

3    return User.builder(a).name(" zhang ").age(14).build(a);

4}

Copy the code

You only need to define it once in the abstract class, and you just need to add the @Autowired annotation to the set method to inject classes from the Spring container.

1private User user;

2

3@Autowired

4public void setUser(User user){

5    this.user = user;

6}

Copy the code

Then call the getUser() method directly in the subclass

1@Override

2public String getMessage() {

3    log.info("name: {},age: {} ",getUser(a).getName(),getUser(a).getAge());

4    return "one";

5}

Copy the code

How do I use @Autowired in an enumerated class

The reason for using @autowired in an enumerated class is because I combined the chain of responsibility design pattern with the policy pattern in my requirements. If you don’t understand the policy pattern, please refer to my previous article design pattern — Policy Pattern. We can use enumerated classes to make our code more visible.

We define a simple enumeration class for the enumeration policy pattern. For example, if we want to use the Spring container class in this case, how do we write it? For example, the User class.

 1public enum  HumanEnum {

2

3    MAN("man") {

4        @Override

5        public void invoke(
{

6            log.info("i am man");

7        }

8    },

9    WOMAN("woman") {

10        @Override

11        public void invoke(
{

12            log.info("i am woman");

13        }

14    };

15

16    String value;

17

18    HumanEnum(String value) {

19        this.value = value;

20    }

21

22    public abstract void invoke();

23}

Copy the code

You simply define an inner class in the enumerated class and assign the injected class to the enumerated class.

 1User user;

2

3public void setUse(User user){

4    this.user = user;

5}

6

7@Component

8public static class HumanEnumInjector{

9

10    @Autowired

11    private  User user;

12

13    @PostConstruct

14    public void setValue(a){

15        for (HumanEnum humanEnum : EnumSet.allOf(HumanEnum.class)){

16            humanEnum.setUse(user);

17        }

18    }

19}

Copy the code

This article code address

conclusion

Object – oriented three characteristics: encapsulation, inheritance, polymorphism

  1. Most design patterns have evolved around three characteristics of object orientation
  2. @AutowiredIt can also be defined on methods, which were traditionally defined on fields
  3. Pay attention to the foundation, complex design is certainly through a simple design will be its pieced together