Spring Container Decorator mode application solution for free combination of business class and service class

Source: Internet
Author: User
Tags get ip object object syslog throwable

There are two kinds of beans that are indispensable in any project, one is the bean that implements the core function of the system, we call it the business class, and the other is the service bean which is not related to the core business of the system but also provides very important service beans. The bean of the business class can be as many as possible depending on the core functions of each system, but the difference between the types of service classes in each system is not very large. The services used in the system are as follows: Privilege service, log service, cache service, transaction service and early warning service, etc. In the process of continuous evolution of the whole system, the relationship between service class and business class is changing constantly, from the original vertical mode to the crosscutting mode, which is also the process of the evolution of programming thought. Service classes and business classes should not be coupled together, otherwise it will not only result in a lot of code redundancy but also difficult to make a controllable change to the service. So how do you solve the problem of providing different services to different business classes on their own request? Spring AOP gives the perfect solution. The core idea of spring's solution to this problem is to put the service class and the business class into the spring container management, dynamically configure the service class according to different requirements of different business classes, that is, the free combination of the dynamic and the business class implementation of the service class. The evolution of the relationship between the business class and the service class can be simply presented:

This picture is the most primitive business-service relationship diagram, see this even want to think, the same service repeated in more than N business, think is also drunk, if which day service content changes in addition to jumping off estimate there is no other choice, fortunately, the advent of spring AOP will be the headache of the problem. Using spring annotations to cross-slice the facets into each service class can solve the problem of code redundancy and difficult to maintain.


This figure is summarized in the code as follows:

Package com.test.util; @Aspectpublic class Authorityservice {@Autowiredprivate Logmanager logmanager; @Before (" Execution (* com.test.web.*.* (..)) ") public void Logall (Joinpoint point) throws Throwable {System.out.println ("======authority-before======");} @After ("Execution (* com.test.web.*.* (..))") public void After () {System.out.println ("=========authority-after=========");} Before and after method execution call @around ("Execution (* com.test.web.*.* (..))") Public Object around (Proceedingjoinpoint point) throws Throwable {System.out.println ("====== Authority-around before starting before====== "); HttpServletRequest request = ((servletrequestattributes) requestcontextholder.getrequestattributes ()). GetRequest () ;//Get verbose time simpledateformat df = new SimpleDateFormat ("Yyyy-mm-dd HH:mm:ss");//Calendar CA = calendar.getinstance ();//St Ring Operdate = Df.format (Ca.gettime ()); Log SysLog = new log ();//Start Time Syslog.setstarttime (Df.format (New Date ()));//Get IP address string ip = tcpiputil.getipaddr ( request); String LoginName; String name; String Methodremark = Getmthodremark (point); String methodName = Point.getsignature (). GetName (); String packages = Point.getthis (). GetClass (). GetName (); if (Packages.indexof ("$ $EnhancerByCGLIB $$") >-1) {// If it is cglib dynamically generated class try {packages = packages.substring (0, Packages.indexof ("$$"));} catch (Exception ex) {Ex.printstacktrace ();}} Object object;try {//Method_param = Point.getargs ();//Get method parameter//String param= (String) point.proceed (Point.getargs ()); O Bject = Point.proceed ();} catch (Exception e) {//Exception handling log: Log.error (e); throw e;} Syslog.setip (IP); syslog.setclazz (packages); Syslog.setmethod (methodName); Syslog.setmessage (Methodremark);// End Time Syslog.setendtime (Df.format (New Date ()));//Returns the result if (object = = null) {Syslog.setresult ("no return Value");} else { Syslog.setresult (Object.ToString ());} Logmanager.addlog (SYSLOG); System.out.println ("======authority-around before after======"); return object;} @AfterReturning ("Execution (* com.test.web.*.* (..))") public void X () {System.out.println ("-------authority-afterreturning-------");} Get partyThe Chinese note ____ is used to record the user's operation log description public static String Getmthodremark (Proceedingjoinpoint joinpoint) throws Exception {String TargetName = Joinpoint.gettarget (). GetClass (). GetName (); String methodName = Joinpoint.getsignature (). GetName (); object[] arguments = Joinpoint.getargs (); Class Targetclass = Class.forName (targetName); Method[] method = Targetclass.getmethods ();  String Methode = ""; for (Method M:method) {if (M.getname (). Equals (MethodName)) {class[] tmpcs = M.getparametertypes (); if (Tmpcs.length = = arguments.length) {Logger Methodcache = m.getannotation (Logger.class);//get token, NULL if not marked if (Methodcache! = null) {Methode = Methodcache.remark ();} Break;}}} return Methode;}}

From the above code can be seen that the right service class into all the classes under the Com.test.web package all methods, the same time we can set up the cache service class, log service class, etc. into other business classes, and now it seems that the headache of the problem seems to be spring based on @ Aspect-style AOP has been solved, but we have to think about the problem really solved it? We all know that this way of cut-in is too coarse, not all the classes under the same package all methods need such a service, for a very simple example, take the cache service and log service, the log service is required to record in detail it can be cut into any method of any class, but the caching service is not the case, Caching services can only exist in the method of obtaining data of the class, at this point the caching service into the class modification, delete, and so on the method is very wonderful, and then the popular will be any one service may only exist in a specific class of methods, this uncertainty determines the use of only spring @ Aspect annotation method is difficult to solve the problem

What do we need to do now? Fortunately spring also provides AOP based on XML configuration, which in large part compensates for the @aspect, and he can cut different services into different methods according to different configurations, so fine granularity is enough for us to realize the dynamic combination of service to business. It may be asked if spring provides an AOP based on XML configuration, then we just need to configure different services in the XML file not the same can be implemented in the dynamic combination of business and service? Sounds plausible, so it seems that annotation-based AOP seems to be a substitute. But the problem of the efficiency of the program makes us re-measure the way the XML is configured and annotated. Because XML is a dynamic union in the runtime to determine facets, the process of parsing XML will undoubtedly consume system resources, if a large number of AOP configuration configuration in the XML file will not outweigh the loss, and the @aspect way to support the compile-time weaving and do not need to build agents, This makes an advantage in efficiency. So, as long as the XML is mixed with the @aspect way, coarse-grained services such as logging and permission services are cut into the @aspect way, and the use of XML configuration for fine-grained services such as caching services in spring can solve the problem perfectly. Here are two ways to use a combination of examples, first look at the configuration file:

<?xml version= "1.0" encoding= "UTF-8"? ><beans xmlns= "Http://www.springframework.org/schema/beans" xmlns: Xsi= "Http://www.w3.org/2001/XMLSchema-instance" xmlns:aop= "Http://www.springframework.org/schema/aop" xmlns: context= "Http://www.springframework.org/schema/context" xmlns:mvc= "Http://www.springframework.org/schema/mvc" xsi:schemalocation= "Http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/ SPRING-BEANS.XSDHTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP http://www.springframework.org/schema/aop/ spring-aop-3.2.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/ Spring-context-3.2.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/ Spring-mvc-3.2.xsd "><!--Note Scan package--><context:component-scan base-package=" Com.test "/><!--opening annotations-- ><mvc:annotation-driven/><!--access to static resources (js/image)--><mvc:resources location= "/js/" mapping= "/js/* * "/><!--definition View Resolver --><bean id= "Viewresolver" class= "Org.springframework.web.servlet.view.InternalResourceViewResolver" > <property name= "prefix" value= "/" ></property><property name= "suffix" value= ". JSP" ></property ></bean><!--enable spring for @aspectj aspects-based configuration support--&GT;&LT;AOP:ASPECTJ-AUTOPROXY&GT;&LT;/AOP: Aspectj-autoproxy><bean id= "Logservice" class= "Com.test.util.LogService" ></bean><bean id= "            Cacheservice "class=" Com.test.util.CacheService "></bean> <aop:config proxy-target-class=" true "> <aop:aspect ref= "Cacheservice" > <aop:pointcut id= "Log" expression= "Execution (* com.test.web . Usercontroller.getalluser (..)) " /> <aop:before pointcut-ref= "log" method= "Logall"/> <aop:after pointcut-ref= "Log "Method=" after "/> <aop:after-returning pointcut-ref=" Log "method=" x "/> <aop:aro    und pointcut-ref= "Log" method= "Around"/>        </aop:aspect> </aop:config></beans> 

Next is the Log service class:

Package com.test.util; @Aspectpublic class Logservice {@Autowiredprivate Logmanager logmanager; @Before ("Execution (* Com.test.web.*.* (..)) ") public void Logall (Joinpoint point) throws Throwable {System.out.println ("======log-before======");} @After ("Execution (* com.test.web.*.* (..))") public void After () {System.out.println ("=========cache-after=========");} Before and after method execution call @around ("Execution (* com.test.web.*.* (..))") Public Object around (Proceedingjoinpoint point) throws Throwable {System.out.println ("======log-around before start before==== =="); HttpServletRequest request = ((servletrequestattributes) requestcontextholder.getrequestattributes ()). GetRequest () ;//Get detailed time SimpleDateFormat df = new SimpleDateFormat ("Yyyy-mm-dd HH:mm:ss"); Log SysLog = new log ();//Start Time Syslog.setstarttime (Df.format (New Date ()));//Get IP address string ip = tcpiputil.getipaddr ( request); String LoginName; String name; String Methodremark = Getmthodremark (point); String methodName = Point.getsignature (). GetName (); String packages = Point.getthis(). GetClass (). GetName (); if (Packages.indexof ("$ $EnhancerByCGLIB $$") >-1) {//If it is cglib dynamically generated class try {packages = Packages.substring (0, Packages.indexof ("$$")); catch (Exception ex) {ex.printstacktrace ();}} String operatingcontent = "";//object[] Method_param = null;object object;try {//Method_param = Point.getargs (); Gets the method parameter//String param= (String) point.proceed (Point.getargs ()), Object = Point.proceed ();} catch (Exception e) {//Exception handling log: Log.error (e); throw e;} Syslog.setip (IP); syslog.setclazz (packages);//Package name + method name//Packages + "." + Methodnamesyslog.setmethod (methodName); Syslog.setmessage (Methodremark);//End Time Syslog.setendtime (Df.format (New Date ()));//return result if (object = = null) { Syslog.setresult ("No return Value");} else {Syslog.setresult (object.tostring ());} Logmanager.addlog (SYSLOG); System.out.println ("======log-around before after======"); return object;} @AfterReturning ("Execution (* com.test.web.*.* (..))") public void X () {System.out.println ("-------log-afterreturning-------");} Get the Chinese notes of the method ____ used for the record employmentThe user's operation log describes public static string Getmthodremark (Proceedingjoinpoint joinpoint) throws Exception {String TargetName = Joinpoint.gettarget (). GetClass (). GetName (); String methodName = Joinpoint.getsignature (). GetName (); object[] arguments = Joinpoint.getargs (); Class Targetclass = Class.forName (targetName); Method[] method = Targetclass.getmethods ();  String Methode = ""; for (Method M:method) {if (M.getname (). Equals (MethodName)) {class[] tmpcs = M.getparametertypes (); if (Tmpcs.length = = arguments.length) {Logger Methodcache = m.getannotation (Logger.class);//get token, NULL if not marked if (Methodcache! = null) {Methode = Methodcache.remark ();} Break;}}} return Methode;}}

Next is the cache service class;

Package Com.test.util;public class Logservice {@Autowiredprivate CacheManager logmanager;public void Pointcut () {} public void Logall (Joinpoint point) throws Throwable {System.out.println ("======cache-before======");} public void After () {System.out.println ("=========cache-after=========");} The method executes before and after calling public Object around (Proceedingjoinpoint point) throws Throwable {System.out.println ("====== Cache-around before starting before====== "); HttpServletRequest request = ((servletrequestattributes) requestcontextholder.getrequestattributes ()). GetRequest () ;//Get verbose time simpledateformat df = new SimpleDateFormat ("Yyyy-mm-dd HH:mm:ss");//Calendar CA = calendar.getinstance ();//St Ring Operdate = Df.format (Ca.gettime ()); Log SysLog = new log ();//Start Time Syslog.setstarttime (Df.format (New Date ()));//Get IP address string ip = tcpiputil.getipaddr ( request); String LoginName; String name; String Methodremark = Getmthodremark (point); String methodName = Point.getsignature (). GetName (); String packages = Point.getthis (). GetClass (). GetName (if (Packages.indexof ("$ $EnhancerByCGLIB $$") >-1) {//If it is cglib dynamically generated class try {packages = packages.substring (0, packages . IndexOf ("$$"));} catch (Exception ex) {ex.printstacktrace ();}} Object object;try {//Method_param = Point.getargs ();//Get method parameter//String param= (String) point.proceed (Point.getargs ()); O Bject = Point.proceed ();} catch (Exception e) {//Exception handling log: Log.error (e); throw e;} Syslog.setip (IP); syslog.setclazz (packages);//Package name + method name//Packages + "." + Methodnamesyslog.setmethod (methodName); Syslog.setmessage (Methodremark);//End Time Syslog.setendtime (Df.format (New Date ()));//return result if (object = = null) { Syslog.setresult ("No return Value");} else {Syslog.setresult (object.tostring ());} Logmanager.addlog (SYSLOG); System.out.println ("======cache-around before after======"); return object;} public void X () {System.out.println ("-------cache-afterreturning-------");}}

The Log service class and the cache service class are not the same only in the specific processing process, this article on the basis of the log service a little change to simplify processing, we can be used in accordance with their own circumstances of the cache processing and log processing. In the specific operation of the careful friend may find in the configuration file in the order of the appearance of different services to determine the order of execution of two services, that is, the spring AOP to perform the cut-in action is done through the decorator mode, using a similar stack of advanced after-out way to implement the service specifically, we must pay attention to AH.

Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

Spring Container Decorator mode application solution for free combination of business class and service class

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.