Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

A Framework on how to improve Development efficiency with Java reflection

2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/01 Report--

This article introduces the knowledge of "how to use Java reflection to improve the efficiency of development framework". In the operation of actual cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

Based on spring's aop, define an annotation as a pointcut, comment on the paging query method of the service layer, and declare which field of the method's return result POJO object needs to apply the default value rule.

After the method execution is completed through aop, the configured default value rule is applied to the returned result, and then returned to the front end, as shown in the following figure.

If a query returns an array of 20 elements of List, you need to reflect and look up Field for each element R to determine the value of the Field. If it is empty, the value is assigned to the default value, that is, repeat reflection to obtain Field, misuse reflection, and extend the response time of the interface.

For the example of applying the default value rule, we can have a good practice of getting the name field in class R, that is, Field, which only needs to be reflected once. That is, when the application starts, perform a packet scan to get the Class object of R, perform reflection to get all the Field in the R type, and then cache it in memory using Map, so that you can get it quickly when you use it. Although it consumes some memory, this is negligible because there are few classes that apply default rules to the entire system.

I think this set of default value rules I designed is the best solution.

1. Use aop to decouple the code. The application logic of the default value rule does not invade the business code, and this function can be plugged and unplugged at any time.

2. At the same time, using reflection, you can add default rules without changing any code, add them at any time, and modify them to take effect at any time.

3. Furthermore, because there are few changes in the default value rules, the use of in-memory cache to effectively reduce the number of database queries is also an improvement in performance.

... Use reflection to improve productivity.

Introduction to business scenario

Today, I continue to share the use of another reflection, including how to design and implement it. In this way, to answer the question at the beginning of this article, how to use it on the edge.

First understand some simple business scenarios, this section mainly introduces the use of scenarios, do not understand it, probably go through it.

What is optimized this time is a scheduled task service, what it needs to do is to call many third-party interfaces to pull the data, and convert the data into the unified structure of the platform, such as A, B, C … Change to P and store it in the database.

If I have a product that needs to be promoted, then I am the upstream advertiser, and I want to put it on Baidu search and Wechat moments, then Baidu and Wechat are the downstream channels. But the middle may go through several layers of channels, and each channel in the middle is an advertiser for the downstream, can also be called the network alliance platform, we may have heard of the Baidu network alliance advertising platform.

So as a network alliance platform, we need to integrate the upstream Offer and grant it to the downstream to display. To integrate upstream Offer is to invoke the api provided by each upstream. However, the json data returned by each upstream is different, and the field name is also different. Then you need to implement a method of parsing mapping for each api. This is repetitive work. How to reduce this repetitive work is to improve work efficiency.

In a word, what do you want to do?

Similar to the process implemented by Mybatis to map query results to pojo objects. If you still think this paragraph is abstract, just skip it. I changed it several times and found it very difficult to express it clearly.

Parsing mapping is to parse the java object Response obtained from json data, then obtain the value of the field in Response that stores the advertising information array (List), and then traverse the List to change each element from type A to platform unified type object B. this process is A to B, for example.

Class A {

String a_name

}

Class B {

String name

}

The implementation of A > to = = > B is:

An a

B b

B.setName (a.getA_name ())

Obviously, it is useless to directly use the value of the reflection copy field, first, the field name is different, second, the type of possible field is also different, and third, this may also be the case below.

Class A {

C c

Public static class C {

String c_name

}

}

Class B {

String name

}

The implementation of A > to = = > B is:

An a

B b

B.setName (a.getC (). GetC _ name ())

How to realize automatic Mapping

If you can add a comment, declare the mapping rules in the comment, such as one: the name field in class A corresponds to the pkgName field in class B.

If you can automatically map according to the mapping rules declared by the annotations, you don't have to write these repetitive code every time. Yes, that's what I'm trying to achieve.

P.S: finally, I added plug-ins to meet some of the needs that require special processing.

Definition of class structure tree

You know why I call it the structural tree? Binary tree is not binary tree, n difference is not n fork tree, I don't know how to call it, is it my own invention? Ha ha.

For example, it's not so abstract. As shown in the figure, the implementation automatically gets the value of List rowset from the TestResponse object. Because according to the docking document, I know that this field is the advertisement Offer collection, and an item represents an advertisement Offer.

To automatically parse TestResponse objects into List collections based on annotations, you must know the structure of TestResponse objects like the back of your hand (this type of object returned by calling API is called a Response object below). So you need to map the field information in the TestResponse class to a tree.

Without saying so much, let's take a look at the final effect and declare the mapping rules using the @ ProdCampaignMapRules annotation.

As shown in the figure above, I added the @ ProdCampaignMapRules annotation to the RowsetBean class, which means that objects of type RowsetBean are automatically mapped to generate ProdCampaign objects.

If you take a closer look, you will find that there is an annotation @ MapRulesComponent on the TestRhost class, which simply declares that the class supports automatic mapping. When I start the program, I scan all the Response annotated by the annotation, parse the Response into a class structure tree, and cache it in memory.

Realize the steps of automatically parsing the Offer array of advertisements returned by API and mapping to generate a unified ProdCampaign collection of the platform. Continue the example in the above figure.

Step 1: from the class structure tree, find the ClassNode with @ ProdCampaignMapRules, and then get the FieldNode to which the ClassNode belongs. The FieldNode found is the List rowset field in Response. Gets the value of rowset, which results in a collection of advertising Offer.

Step 2: New a List, iterate through the advertising Offer collection rowset, convert each RowsetBean type element into a platform-unified ProdCampaign object, and add it to the List collection.

Step 3: in the process of converting each RowsetBean to ProdCampaign, you need to new a ProdCampaign object, and then assign values to the fields in that object. Where does the value come from? Find the corresponding field from the RowsetBean object, get the value, and assign a value to the ProdCampaign object. It's easy to understand, it's just a copy of the attribute.

Step 4: if it is a multi-layer mapping, such as the "offer.name" mapping rule in the example, you need to get the offer field in the RowsetBean object first, with the type OfferBean. Go on to the next layer of name mapping, which is to get the name field of OfferBean. This is an example of a two-tier mapping.

The structure I defined looks very complex. RuleMetaData is the class structure tree generated by each Class after the package scan is completed. The field information in the class is stored in FieldNode. If the type of the field is a non-basic data type, then the child of FieldNode is the ClassNode data of the corresponding type of the field.

The whole structure tree is a RuleMetaData, and the root node root must be a ClassNode. Non-basic data types of FieldNode also have a child pointing to a ClassNode. Abstract? It doesn't matter, keep looking, there will be a picture below, vividly drawing the number of this structure.

Implement packet scanning to parse Class into a structure tree

When the application starts, the package is scanned, all the classes annotated by @ MapRulesComponent are found, and the structure tree RuleMetaData is parsed, for example.

As in the picture, it has been painted very vividly, and the structure of this tree should already be in your mind.

The root node of the structure tree, which is the first field of the Response, stores the field name of this field and the reflected Field, which belongs to the class TestResponse. The next field is the nextField field of the node, and because the type of this field is the basic data type int, the value of child is null.

When it comes to the data field, because its type is a non-basic data type, but an inner class DtaBean, it needs to be parsed into a ClassNode, while continuing to reflect the chain of FieldNode nodes that get all the fields of DataBean. Finally, point the child of the data node to the ClassNode.

When the reflection DataBean generates the FieldNode chain, you process the rowset field and find that it is a List type, then get the type of the element of the List. This reflection is supported and can be obtained.

Then continue with the above steps for RowsetBean. Another thing is that RowsetBean is annotated by the @ ProdCampaignMapRules annotation, so get the @ ProdCampaignMapRules annotation and assign the rule to the ClassNode node of the rowset.

Reflection parsing Response generates the number of structures, I am using the queue plus breadth-first traversal method. The code is shown in the following figure.

I won't say how packet scanning is realized.

Generate ProdCampaign according to the Class structure tree mapping of OfferBean

This step I only introduce the implementation of ideas, the specific implementation of each step, the overall implementation of the code will not be posted.

1. First, use jackson to parse the json string returned by the third-party API, and get the Response object.

two。 Get the class structure tree from the cache based on Response's Class. Use depth-first search to get the ClassNode annotated by @ ProdCampaignMapRules. This is easy to judge, because the previous step of generating the structure tree for the class has taken the @ ProdCampaignMapRules annotation and stored it in ClassNode's rule.

3. After getting the ClassNode annotated by @ ProdCampaignMapRules, get the FieldNode to which the ClassNode belongs.

4. After getting the FieldNode, get the Field, and reflect to get the value, which is the target you are looking for, that is, the collection that holds the advertising Offer.

5. After getting the collection that stores the advertising Offer, iterate through the collection and map each element in it into a unified ProdCampaign for storing advertising information on the platform. Finally, you can get the ProdCampaign collection.

6. The process of mapping each element to a ProdCampaign object is the key and complex. Because it needs to support multi-layer mapping, it supports "." just like using mybatis to spell sql. An operation, such as "offer.geo.country", is to get the value of the geo field of the offer object, and then get the value of the country field of geo. With the class structure tree, multi-level mapping is not difficult, just a while loop is needed.

7. For tracklinkMap, it is an annotated array of type @ TracklinkMap that declares which parameters url requires and how to concatenate them.

This is the end of the content of "Framework on how to improve Development efficiency with Java reflection". Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report