Task requirements
The database of system a defines a document table to store the basic information of the document. When you add, delete, and modify the table data, you must send a message to system B, notify them to perform corresponding processing. The message content includes the document change type and document data information.
Demand implementation
The simplest processing method we can think of is as follows:
Data modification and message sending are two independent functions, but the doaction method is coupled together. There is no problem with the method processing. However, with the passage of time, the demand changes, to disable a message, you must modify the code at the business layer and comment out the sendmessage method.
Can we avoid hard coding in a more elegant way?
The service container concept is introduced in the preceding processing method. messageservice is equivalent to a functional plane, while the Spring framework is equivalent to a functional plane container.
The doaction method uses tags to declare dependencies on MNS. If the container contains MnS, the message is triggered when data is modified. If no, then, only the data modification is processed.
The advantage of such processing is that the coupling degree between services is more loose, and the service requirements can be changed through service plugging. If you want to disable messages, you only need to remove the message plane from the spring container without modifying any code.
Implementation Details
First define the message service aspect
The Section consists of the starting point and notification. The @ aspect label is used in aspectj to declare
@ Aspectpublic class sendmessageadvice {Private Static final logger log = loggerfactory. getlogger (sendmessageadvice. class); @ pointcut ("@ annotation (Org. chen. aopdemo. sendmessage) ") Public void send () {}@ around (" Send () ") Public void dosendmessage (final proceedingjoinpoint pjp) throws throwable {pjp. proceed (); // execute the intercepted method // obtain the intercepted method name methodsignature msig = (methodsignature) pjp. getsignature (); string name = msig. Getname (); Class <?> [] Parameters = msig. getparametertypes (); object target = pjp. gettarget (); Method method = target. getclass (). getmethod (name, parameters); // obtain the intercepted method // whether the generic parameter if (method. isbridge () {class <?> Erasedparam = NULL; Class <?> Targetparam = NULL; annotation [] annotations = target. getclass (). getannotations (); First: For (annotation: Annotations) {If (annotation instanceof bridgemethodmappings) {comment mappings = (bridgemethodmappings) annotation; For (comment mapping: mappings. value () {If (mapping. methodname (). equals (name) {erasedparam = mapping. erasedparamtypes () [0]; targetparam1_mapping.tar getpar Amtypes () [0]; break first ;}}// Replace the generic parameter with the specified parameter for (INT I = 0; I <parameters. length; I ++) {If (parameters [I]. equals (erasedparam) {parameters [I] = targetparam ;}}// obtain the method declaration method = target. getclass (). getmethod (name, parameters); // obtain the intercepted method} sendmessage sendmsg = method. getannotation (sendmessage. class); // obtain the sendmessage tag signaltype singletype = sendmsg declared by the method. single (); // obtain the message type declared by the tag annotation [] [] annotatio NS = method. getparameterannotations (); integer msgdataindex = NULL; // obtain the first: For (INT I = 0; I <annotations. length; I ++) {annotation [] paramannotation = Annotations [I]; for (Int J = 0; j <paramannotation. length; j ++) {If (paramannotation [J] instanceof messagedata) {messagedata msgdata = (messagedata) paramannotation [J]; If (msgdata. order () = 0) {msgdataindex = new INTEGER (I); break first ;}}} if (msgdataindex! = NULL) {serializable OBJ = (serializable) pjp. getargs () [msgdataindex]; // get method parameter value dosendmessage (singletype, OBJ); // execute the message sending operation to pass the message type and message data log.info ("message sent successfully, message Type: "+ singletype. getop () + ", message data:" + OBJ );}}}
The @ pointcut label declares the entry point of the message service. If the sendmessage label is declared by the method, the method is intercepted to process the sent message.
The @ around label declares the notification, and the method describes the specific operation for sending the message.
Then inject the Message Service plane into the spring container.
Add the following configuration in the spring configuration file:
<aop:aspectj-autoproxy /><bean id="sendMessage" class="cn.com.gei.krp.ecm.core.index.jms.SendMessageAdvice"><property name="jmsurl" value="tcp://user-df29b9c8dc:61616?jms.useAsyncSend=true" /></bean>
Finally, declare dependencies on the message service in the documentdao method (using the sendmessage tag)
@ Bridgemethodmappings ({@ bridgemethodmapping (methodname = "delete", erasedparamtypes = {serializable. class}, targetparamtypes = {string. class}), @ bridgemethodmapping (methodname = "Update", erasedparamtypes = {object. class}, targetparamtypes = {document. class}), @ bridgemethodmapping (methodname = "insert", erasedparamtypes = {object. class}, targetparamtypes = {document. class}),}) public class documentdao extends simplehibernatedao <document, string> implements idocumentdao {@ override @ sendmessage (type = messagetype. deletedocument) Public void Delete (@ messagedata string ID) {super. delete (ID) ;}@ override @ sendmessage (type = messagetype. updatedocument) // declare that mns depends on public void Update (@ messagedata document entity) {super. update (entity) ;}@ override @ sendmessage (type = messagetype. adddocument) Public void insert (@ messagedata document entity) {super. insert (entity );}}
In this way, when adding, deleting, modifying, and deleting a document, if spring declares the message service, the message sending process will be executed. Otherwise, only the original operation will be executed.