This is the 29th day of my participation in the More Text Challenge. For more details, see more Text Challenge

preface

  • In the previous two articles, we introduced the introduction of reflection and annotation respectively, and some students suggested that it be easier to understand the essence from the specific application scenario! Today, I will combine the functions used in my actual project! This is a good place to start

The functional requirements

  • Do a form query function for a table! This feature is very simple and there is no technical difficulty except that when we write a query we inject conditions and write dynamic conditions! Not much else

  • Related to the company’s internal data, here the key data has been replaced by me!
  • In addition to querying, we also have the ability to generate data. With the management of the data let’s look at how do we annotate reflection both

The data shows that

  • First the data is stored inmongo, the query is passedMongoTemplateTo achieve data query
  • Stored data time Data is a timestamp that needs to be formatted for page presentation. This part is handled by the interface
  • About data StateAcceptance and,No acceptanceThe actual storage is 1 and 2
  • Condition query is currently the above several! It needs to be adjusted at regular intervals according to the frequency of use and user feedback

Entities defined

@Data
public class DangersBook implements Serializable {
    @TimeSequence
    @Ignore
    @Id
    @Query
    private Long id;
    @DangersNo
    @Ignore
    @Query
    @LikeQuery
    private String dangersNo;
    @Ids
    private String instance_id;
    @DangersType
    @Ids
    private String app_id;
    @Ids
    @Query
    @DangersEntId
    @OrQuery
    private String entId;
    private String created_by;
    @Query
    @Ids
    private String zuoyeleixing;
    @Date
    @Query
    private String pizhunkaishi;
    @Date
    @Query
    private String pizhunjieshu;
    @updateItem (value = "accepted ")
    @Query
    @OrQuery
    private String yanshouStatus;
    @Query
    @Date
    @UpdateItem(value = "")
    private String finishTime;
    private String jianweixiuxukezheng;
    private String zuoyedengji;
    @Query
    @LikeQuery
    private String zuoyeneirong;
    / * * *@DescriptionUsed to determine whether the number */ should be generated
    @Ignore
    @Query
    private String createDangerNo;
    private String laowubanzu;
    @Query
    private String test;
    @Query
    private String interrupt;
    @Query
    @OrQuery
    private String year;
}
Copy the code

Note that

  • First we need to get it by reflectionDangersBookAll properties in! This is our first use of reflection! In fact, in the project any need to write live attributes are obtained through reflection to obtain attributes combined with annotations filtering!

TimeSequence

  • When the data is generated, the unique ID of the data is often generated by the back end so as to ensure that the real unique! The TimeSequence annotation is to annotate the field, so that we will generate the unique ID whenever we recognize the existence of the annotation in the attribute in the program
TimeSequence annotation = declaredField.getAnnotation(TimeSequence.class);
if(annotation! =null) {
    // Snowflake algorithm
    long generatorId = DistributedIDUtils.getInstance().getGeneratorId(1l.2l.3l);
    declaredField.setAccessible(true);
    declaredField.set(object, generatorId);
}
Copy the code
  • Access to theTimeSequenceAnd then we can use the snowflake algorithm to generate the ID and then we can use the attribute to assign the generated ID to it!

Ignore

  • There are also cases where there is data that we can’t do anything with, so we need to filter it out when we update the data by retrieving it through annotations in reflection.IgnoreThat’s what it does
Ignore ignore = declaredField.getAnnotation(Ignore.class);
if(ignore ! =null) {
    continue;
}
Copy the code

Query & Date & LikeQuery&OrQuery

  • All three are involved in the query. The last two are also inQueryBased on the extension
com.ay.sdksm.custom.components.expose.annation.Query queryField = declaredField.getAnnotation(com.ay.sdksm.custom.components.expose.annation.Query.class);
if(queryField ! =null) {
    // Query conditions need to be added
    try {
        declaredField.setAccessible(true);
        Object o = declaredField.get(dangersBook);
        if (null! = o&&!"".equals(o.toString())) {
            String svalue = o.toString();
            Date dateAnnotation = declaredField.getAnnotation(Date.class);
            LikeQuery likeQuery = declaredField.getAnnotation(LikeQuery.class);
            if(dateAnnotation ! =null) {
                String dateValue = svalue;
                if (StringUtils.isEmpty(dateValue)) {
                    continue;
                }
                String[] dateSplit = dateValue.split(",");
                String start = dateSplit[0];
                String end = start;
                if (dateSplit.length >= 2) {
                    end = dateSplit[1];
                }
                criteria.and(declaredField.getName()).gte(start).lte(end);

            } else if(likeQuery ! =null){
                Pattern pattern = Pattern.compile(String.format(".*%s.*", svalue), Pattern.CASE_INSENSITIVE);
                criteria.and(declaredField.getName()).regex(pattern);
            }else {
                OrQuery orQuery = declaredField.getAnnotation(OrQuery.class);
                if (null! = orQuery) { String[] split = svalue.split(",");
                    String start = split[0];
                    String end = split[0];
                    if (split.length > 1) {
                        end = split[1];
                    }
                    criteria.and(declaredField.getName()).in(start, end);
                } else {
                    if (svalue.contains("$ne")&& JsonUtils.getInstance().isJson(svalue)) {
                        JSONObject jsonObject = JSONObject.parseObject(svalue);
                        String $ne = jsonObject.getString("$ne");
                        criteria.and(declaredField.getName()).ne($ne);
                    }else if(svalue.contains("$like")&& JsonUtils.getInstance().isJson(svalue)){
                        // Fuzzy query
                        JSONObject jsonObject = JSONObject.parseObject(svalue);
                        String $like = jsonObject.getString("$like");
                        criteria.and(declaredField.getName()).is(String.format("/%s/",$like));
                    } else{ Class<? > type = declaredField.getType();if (type == Long.class) {
                            criteria.and(declaredField.getName()).is(Long.valueOf(svalue));
                        } else {
                            criteria.and(declaredField.getName()).is(svalue);
                        }
                    }
                }
            }
        }
    } catch(IllegalAccessException e) { e.printStackTrace(); }}Copy the code
  • First of all you need to cooperateQueryAnnotations indicate that conditional assembly of fields is required. When we’re dealing with Date, we need to customize the conditional value and our convention is that the conditional value is a period of time separated by commas. In this way, we can dynamically support point-in-time and time-range queries.
  • And then meetLikeQueryIt is a fuzzy query.
  • There are also part of the case is to take the inverse query! In short, all of our requirements can be extended after annotating the Query base. This is an early version of it and it’s not designed to show that there are some if else honor codes! I’m just showing you how annotations are used.
  • Later or if the reader has time to optimize the code according to the policy pattern in the design pattern, it will be easy to understand! This article is enough for the strategy pattern

DangersNo

DangersNo annotation = declaredField.getAnnotation(DangersNo.class);
if(annotation ! =null) {
    // Generate data ID in the specified format according to the business; It's a little bit complicated here. Code omission...
}
Copy the code

Annotations are summarized

  • In general, we can develop different annotations to represent different functions according to our different business needs. And then in the reflection of all the same people to treat! We do business development when we encounter the specified annotation! And this fits nicely into the policy pattern and in the code we can also simplify our if else.

Reflection Application Scenarios

  • The usage scenarios annotated above can also be understood as reflection usage scenarios. But that’s mostly about annotations. Reflection is mostly used in the framework, because the framework needs to be highly adjustable so many internal configuration to take effect.
  • Spring should not be unfamiliar to back-end programmers. Two skill points that are common and necessary in Spring are IOC+AOP.

IOC

  • In IOC dependency injection, the object we need in Spring no longer needs to be New in the traditional way. Instead, we can easily obtain an object through the injection function of Spring. This is not only a change in the way, but also a simplification of our operation. We no longer need to initialize complex properties for a newly created object and that’s all done by Spring. The main way he does this is through reflection. Spring gets the properties from the reflection and populates them when the project is initialized! This is a complicated process and we just need to remember today that we do property initialization by reflection at the beginning of the project! We can operate directly from class objects as we use them

AOP

  • AOP aspect programming. Your project must have a logging function, and every interface needs to record the basic information of the interface, including the input and output parameters and the time consuming. If you want to implement whether you need to develop everywhere. In this way, we can understand the operation as a buried point. This is not an option. Because of something as generic as logging, we can’t develop it everywhere. It’s time consuming!
  • In IOC, not only do you initialize properties by reflection, but you also generate proxy objects. The generation process of this proxy object is to understand it as a reflection generated proxy object. I don’t know if this is correct? If you forget to point out a mistake.

conclusion

  • Reflection Some people say affects performance. This does affect performance, but it increases the flexibility of our program. As I said before, it’s a matter of time and space! You can’t have your cake and eat it
  • Annotations exist in any framework. A mature framework must be annotated in order to increase productivity

Thumb up, XDM