Common Java projects introduce Aspectj__java when using gradle constructs

Source: Internet
Author: User
Tags getmessage

An ordinary Java project, if you want to weave extra code into some classes, a better choice is ASPECTJ, which has the least intrusion on the project, just write a aspectj slice file, and then use the build tool to introduce the ASPECTJ plug-in (Gradle, maven), It will be able to weave the code you want at compile time.

We have a project that uses quartz timed tasks, there are a lot of jobs, and now you want to monitor the job and the job executes. Job execution succeeded. The basic idea is to execute the start record at each job, execute the end record, and throw the exception record. There are two kinds of schemes. One is to write an abstract class in which all jobs inherit from this class, which is processed after the job actually executes the method and throws the exception.

/** * @author Xiongshiyan at 2018/3/2/public class Jobexecute extends model<jobexecute> {public static fin
    Al String id = "id";
    public static final String day = ' Day ';
    public static final String start = "Start";
    public static final String end = ' End ';
    public static final String job_name = "JobName";

    public static final String is_success_finished = "issuccessfinished";
    public static final int SUCCESS = 1;

    public static final int FAIL = 0;

    public static final Jobexecute DAO = new Jobexecute (); /** * Job at the beginning of the record, description began to execute * @param day * @param start time * @param jobName jobName * @return Jobexecute later update Some fields of this model * * Public jobexecute Insertstart (Date day, date start, String jobName) {Jobexe
        Cute execute = new Jobexecute ();
        Execute.set (Jobexecute.day,day);
      Execute.set (Jobexecute.start,start);  Execute.set (Jobexecute.job_name,jobname);
        Execute.set (Jobexecute.is_success_finished,fail);
        Execute.save ();
    return execute;
        /** * Update field at the end of normal */public void Updateend () {This.set (end,new Date ());
        This.set (is_success_finished,success);
    This.update (); }

}
/** * @author Xiongshiyan at 2018/3/2 * Increase logging at the start and end * ID Day start_time end_time is_success_finished job_name * * Public abstract class Abstractloggingjob implements job{private static final Logger Logger = Loggerfactory.getlogger
    (Abstractloggingjob.class);
        @Override public void Execute (jobexecutioncontext context) throws Jobexecutionexception {//1. Record at the beginning
        Date start = new Date ();
        Jobexecute Execute = JobExecute.dao.insertStart (start, Start, JobName ());
        2. Start job try {exe (context);
            catch (Exception e) {logger.error (JobName () + "Exception occurred:" + e.getmessage (), E);
        An exception is thrown out, 3 will not execute, end time will be empty throw new Jobexecutionexception (e);
    //3. Update this record at the end Execute.updateend ();

    /** * True Job method, subclass Replication * * protected abstract void EXE (Jobexecutioncontext context) throws Exception; /** * Subclass returns JobName, default is class name * @return job ' s NamE/protected String jobName () {return This.getclass (). GetName (); }
}

This scheme is simpler, but needs to be changed to every job, error prone. In fact, we have adopted the second scheme--using ASPECTJ for weaving.

First we need to meet JDK and gradle conditions, 1.8.0_121 above JDK version, gradle4.1 above. The beginning of my JDK version is 1.8.0_65 are compiled, old in the download dependencies when the error.

Second, we need to introduce GRADLE-ASPECTJ plug-ins and AspectJ dependencies in Gradle's compiled files.

Buildscript {
    repositories {
        maven {
            url ' https://maven.eveoh.nl/content/repositories/releases '
        }
    }

    dependencies {
        classpath "nl.eveoh:gradle-aspectj:2.0"
    }
}

ext.aspectjversion = ' 1.8.13 '
Apply plugin: ' AspectJ '
compileaspect {
	Additionalajcargs = [' Encoding ': ' UTF-8 ', ' source ': ' 1.8 ', ' target ': ' 1.8 ']
}
Compile ' org.aspectj:aspectjrt:1.8.13 '

very Note: Set file encoding, otherwise garbled.

Then, write the AspectJ section file and introduce the slice code, the most important of which is the writing of the expression, see

http://blog.csdn.net/sunlihuo/article/details/52701548.

/** * @author Xiongshiyan at 2018/3/6 * section file/public aspect LOGGINGASPECTJ {private static final Logger Logger =
    Loggerfactory.getlogger (Loggingaspectj.class); Public pointcut Jobs (jobexecutioncontext context): Execution (public void cn.esstx.dzg.runner.tinyrunner.job.

    *.execute (org.quartz.JobExecutionContext)) && args (context);

    Private Jobexecute execute = NULL; Before (Jobexecutioncontext context): Jobs (context) {Logger.info ("[Before]" + Thisjoinpoint
                        . Gettarget (). GetClass (). Getcanonicalname () + "."
        + thisjoinpoint.getsignature (). GetName ());
        Date start = new Date ();
        String jobName = Thisjoinpoint.gettarget (). GetClass (). GetName ();
    Execute = JobExecute.dao.insertStart (start, start, jobName); //There was a successful return stating that execution succeeded, and if the exception would not execute after (Jobexecutioncontext context) returning (): Jobs (context) {Logger.info ( "[After returning]" +Thisjoinpoint.gettarget (). GetClass (). Getcanonicalname () + "."
        + thisjoinpoint.getsignature (). GetName ());
    Execute.updateend ();
                        }///Throw no exception will execute after (Jobexecutioncontext context): Jobs (context) {Logger.info ("after]"
                        + Thisjoinpoint.gettarget (). GetClass (). Getcanonicalname () + "."
    + thisjoinpoint.getsignature (). GetName ()); When the exception is thrown (Jobexecutioncontext context) throwing (java.lang.Exception e): Jobs (context) {Logger.err
                or ("[after throwing]" + thisjoinpoint.gettarget (). GetClass (). Getcanonicalname () + "."
    + thisjoinpoint.getsignature (). GetName () + "throwing=" + e.getmessage ()); }
}

Finally, the execution of the Gradle clean build Gets the implanted class file, the test class is everyminutetestjob, executes two times, throws the exception, and the code following the decompile is as follows.

public class Everyminutetestjob implements JOB {private static int xx;

    private static final Logger Logger;
        static {Ajc$preclinit ();
        xx = 0;
    Logger = Loggerfactory.getlogger (Everyminutetestjob.class); Public Everyminutetestjob () {} public void execute (jobexecutioncontext context) throws Jobexecutionexcept
        Ion {Jobexecutioncontext var2 = context;

        Joinpoint var3 = FACTORY.MAKEJP (Ajc$tjp_0, this, this, context); try {try {loggingaspectj.aspectof (). AJC$BEFORE$CN_ESSTX_DZG_RUNNER_TINYRUNNER_LOGGINGASPECTJ
                $1$DDB27CEC (VAR2, VAR3);
                Logger.info ("Execute method invoked-------");
                ++xx;
                if (xx = = 2) {throw new RuntimeException ("simulation throw a Exception"); } loggingaspectj.aspectof (). AJC$AFTERRETURNING$CN_ESSTX_DZG_RUNNER_TINYRUNNER_LOGGINGASPECTJ$2$DDB27CEC (V
           AR2, VAR3); The catch (Throwable var6) {loggingaspectj.aspectof (). Ajc$after$cn_esstx_dzg_runner_tinyrunner_loggingaspe
                CTJ$3$DDB27CEC (VAR2, VAR3);
            Throw VAR6;
        } loggingaspectj.aspectof (). AJC$AFTER$CN_ESSTX_DZG_RUNNER_TINYRUNNER_LOGGINGASPECTJ$3$DDB27CEC (Var2, VAR3); The catch (Exception var7) {loggingaspectj.aspectof (). Ajc$afterthrowing$cn_esstx_dzg_runner_tinyrunner_
            LOGGINGASPECTJ$4$DDB27CEC (context, VAR7, VAR3);
        Throw var7; }
    }
}
From the decompile file, we can see the execution location of each notification. Before is the target method before, Afterreturning is the return value of the time, indicating the normal execution of the method can be executed results, after the target method is executed, regardless of throwing an exception, afterthrowing is thrown after the exception to execute, Around can be completely controlled.
We print according to the log, we can clearly see this order of execution.
dzg-server-runner-prod:2018-03-06 20:41:00.009 [defaultquartzscheduler_worker-1] INFO (LoggingAspectJ.aj:19)-[ Before]cn.esstx.dzg.runner.tinyrunner.job.everyminutetestjob.execute dzg-server-runner-prod:2018-03-06
20:41:00.047 [Defaultquartzscheduler_worker-1] INFO (everyminutetestjob.java:17)-Execute method invoked------- dzg-server-runner-prod:2018-03-06 20:41:00.049 [defaultquartzscheduler_worker-1] INFO (LoggingAspectJ.aj:30)-[ After Returning]cn.esstx.dzg.runner.tinyrunner.job.everyminutetestjob.execute dzg-server-runner-prod:2018-03-06 20:41:00.057 [Defaultquartzscheduler_worker-1] INFO (loggingaspectj.aj:38)-[after] Cn.esstx.dzg.runner.tinyrunner.job.EveryMinuteTestJob.execute dzg-server-runner-prod:2018-03-06 20:42:00.001 [ Defaultquartzscheduler_worker-2] INFO (loggingaspectj.aj:19)-[before] Cn.esstx.dzg.runner.tinyrunner.job.EveryMinuteTestJob.execute dzg-server-runner-prod:2018-03-06 20:42:00.010 [ Defaultquartzscheduler_worker-2] INFO (everyminutetestjob.javA:17)-Execute method invoked-------dzg-server-runner-prod:2018-03-06 20:42:00.011 [defaultquartzscheduler_worker-2
] INFO (loggingaspectj.aj:38)-[After]cn.esstx.dzg.runner.tinyrunner.job.everyminutetestjob.execute dzg-server-runner-prod:2018-03-06 20:42:00.011 [defaultquartzscheduler_worker-2] ERROR (LoggingAspectJ.aj:46)-[
After Throwing]cn.esstx.dzg.runner.tinyrunner.job.everyminutetestjob.execute throwing=simulation throw a exception dzg-server-runner-prod:2018-03-06 20:42:00.014 [defaultquartzscheduler_worker-2] ERROR (JobRunShell.java:211)-Job Cn.esstx.dzg.runner.tinyrunner.job.EveryMinuteTestJob.cn.esstx.dzg.runner.tinyrunner.job.EveryMinuteTestJob Threw a unhandled Exception:java.lang.RuntimeException:simulation throw a Exception at Cn.esstx.dzg.runner.tinyrunner . Job.
	Everyminutetestjob.execute (everyminutetestjob.java:20) at Org.quartz.core.JobRunShell.run (jobrunshell.java:202) At Org.quartz.simpl.simplethreadpool$workerthread.run (simplethreadpool.java:573) dzg-server-runner-prod:2018-03-06 20:42:00.014 [defaultquartzscheduler_worker-2] ERROR (quartzscheduler.java:2425)-Job (Cn.esstx.dzg.runner.tinyrunner.job.EveryMinuteTestJob.cn.esstx.dzg.runner.tinyrunner.job.EveryMinuteTestJob
Threw an exception.
	Org.quartz.SchedulerException:Job threw an unhandled exception. At Org.quartz.core.JobRunShell.run (jobrunshell.java:213) at Org.quartz.simpl.simplethreadpool$workerthread.run ( simplethreadpool.java:573) caused by:java.lang.RuntimeException:simulation throw a exception at Cn.esstx.dzg.runner.tinyrunner.job.EveryMinuteTestJob.execute (EVERYMINUTETESTJOB.JAVA:20) at Org.quartz.core.JobRunShell.run (jobrunshell.java:202) ... 1 common frames omitted dzg-server-runner-prod:2018-03-06 20:43:00.002 [defaultquartzscheduler_worker-3] INFO (
loggingaspectj.aj:19)-[Before]cn.esstx.dzg.runner.tinyrunner.job.everyminutetestjob.execute dzg-server-runner-prod:2018-03-06 20:43:00.010 [defaultquartzscheduler_worker-3] INFO (EveryMinuteTestJob.java:17) -Execute method invoked-------dzg-server-runner-prod:2018-03-06 20:43:00.011 [defaultquartzscheduler_worker-3] INFO
(loggingaspectj.aj:30)-[After Returning]cn.esstx.dzg.runner.tinyrunner.job.everyminutetestjob.execute dzg-server-runner-prod:2018-03-06 20:43:00.022 [defaultquartzscheduler_worker-3] INFO (LoggingAspectJ.aj:38)-[ After]cn.esstx.dzg.runner.tinyrunner.job.everyminutetestjob.execute

These are actually very serious thread-safety issues. Because the slice is a single case, so its member variables are modified in different notifications, which can cause a job1 to insert a record and another job2 to insert a record, and the member variable execute becomes another one, job1 update its field after the method call completes. You are not actually updating the field of the original record. So if you need to save change variables across notifications, there's a security issue. You must use around notifications.

Public aspect Loggingaspectaround {private static final Logger Logger = Loggerfactory.getlogger (loggingaspectaround.c
    LASS); Public pointcut jobs (): Execution (public void cn.esstx.dzg.runner.tinyrunner.job.

    *.execute (Org.quartz.JobExecutionContext));
        void Around (): Jobs () {Jobexecute execute = null;
                    try {logger.info ("[Before]" + This + ":" + thisjoinpoint.gettarget (). GetClass ()
                    . Getcanonicalname () + "."
            + thisjoinpoint.getsignature (). GetName ());
            Date start = new Date ();
            String jobName = Thisjoinpoint.gettarget (). GetClass (). GetName ();
            String simplename = Thisjoinpoint.gettarget (). GetClass (). Getsimplename ();

            Execute = JobExecute.dao.insertStart (start, start, jobname,simplename);

            Proceed ();  Logger.info ("[After returning]" + This + ":" + thisjoinpoint.gettarget (). GetClass (). Getcanonicalname () + "."+ thisjoinpoint.getsignature (). GetName ());
        Execute.updateend (); catch (Exception e) {logger.error ("[after throwing]" + this + ":" + Thisjoinpoint.gettar
                    Get (). GetClass (). Getcanonicalname () + "."
            + thisjoinpoint.getsignature (). GetName (), E);
        Execute.updateexception (e);
 }
    }
}



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.