1. Descripción general
En los sistemas generales, cuando hacemos algunas operaciones importantes, como iniciar sesión en el sistema, agregar usuarios, eliminar a los usuarios, etc., necesitamos persistir estos comportamientos. En este artículo, implementamos la inserción de registros a través de anotaciones personalizadas de Spring AOP y Java. Esta solución tiene menos intrusión al negocio original y es más flexible para realizar
2. Definiciones de clase relacionadas de registros
Resumen el registro en dos clases: módulo funcional y tipo de operación
Utilice clases de enumeración para definir el tipo de módulo de tipo de módulo de función, como el módulo de usuario y estudiante
public enum ModuleType {default ("1"), // Valor predeterminado Estudiante ("2"), // Módulo de estudiante maestro ("3"); // Módulo de usuario ModuleType (String Index) {this.module = index; } módulo de cadena privada; public String getModule () {return this.module; }}Use una clase de enumeración para definir el tipo de operación: EventType. Como Iniciar sesión, agregar, eliminar, actualizar, eliminar, etc.
public enum eventType {default ("1", "predeterminado"), add ("2", "add"), update ("3", "update"), delete_single (4 "," delete-single "), login (" 10 "," login "), login_out (" 11 "," login_out "); privado eventtype (índice de cadena, nombre de cadena) {this.name = name; this.event = index; } evento de cadena privada; nombre de cadena privada; public String getEvent () {return this.event; } public String getName () {nombre de retorno; }}3. Definir anotaciones relacionadas con el registro
3.1. @Logenable
Aquí definimos la cantidad de interruptor del registro. Solo cuando este valor sea verdadero en la clase, la función de registro en esta clase estará habilitada.
@Documentado @retención (retenciónPolicy.Runtime) @Target ({elementType.type}) public @interface logenable { / ** * Si es verdadero, el logEvent debajo de la clase estará habilitado, de lo contrario * @return * / boolean logenable () predeterminado;}3.2. @Logevent
Definición del registro aquí. Si esta anotación se anota en la clase, este parámetro se usa como el valor predeterminado para todos los métodos de la clase. Si la anotación está en el método, solo funcionará para este método
@Documentado@retención (retenciónPolicy.Runtime) @Target ({java.lang.annotation.elementType.method, elementtype.type}) public @Interface LogEvent {ModuleType Module () predeterminado ModuleType.default; // El módulo al que el registro pertenece eventtype event () predeterminado eventtype.default; // registrar el tipo de evento String desc () predeterminado ""; // Información de descripción}3.3. @Logkey
Si esta anotación está en un método, los parámetros de todo el método se guardan en el formato JSON log en formato. Si esta anotación se anota tanto en el método como en la clase, la anotación en el método sobrescribe el valor en la clase.
@Target ({elementType.field, elementType.parameter})@retención(CretentPolicy.runtime)@documentedpublic @interface logkey {string keyName () default ""; // El nombre de la clave boolean isuserid () predeterminado falso; // Si este campo es el ID de usuario de esta operación, aquí se omite boolean islog () predeterminado verdadero; // si se agrega al registro}4. Definir la clase de procesamiento de registros
4.1. Logadmmodel
Defina la clase que contiene información de registro
clase pública logadModel {ID de largo privado; String de usuario de cadena privada; // operar el nombre de usuario de la cadena privada del usuario; cadena privada admmodel; // módulo de cadena privada admevent; // Operación fecha privada creó; // Operación contenido de contenido privado String admoptContent; // Operation Content Cadena privada Desc; // Observar establecer/omitir}4.2. Ilogmanager
Definir la clase de interfaz IlogManager para el procesamiento de registros
Podemos almacenar registros en la base de datos o enviar registros para abrir middleware, si redis, MQ, etc. Cada clase de procesamiento de registro es una clase de implementación de esta interfaz
Interfaz pública IlogManager { / *** Módulo de procesamiento de registro* @param paramlogadmbean* / void ojurLog (logAdmmodel paramLogadmbean);}4.3. Dblogmanager
Clase de implementación de IlogManager para almacenar registros. Solo almacenamiento simulado aquí
@ServicePublic Class dblogManager implementa IlogManager {@Override public void DealLog (logAdMModel ParamLogadMBean) {System.out.println ("Almacene el registro en la base de datos, el contenido de registro es el siguiente:" + json.tojsonstring (paramLogAdmBean)); }}5. Configuración de AOP
5.1. LogAspect define la clase AOP
Anotar esta clase con @Aspect
Use @Pointcut para definir el paquete y los métodos de clase para interceptar
Usamos @around para definir el método
@Componente @AspectPublic Class LogAspect {@aUtowired Private Loginfogeneration Loginfogeneration; @Autowired Private IlogManager LogManager; @PointCut ("Ejecution (*com.hry.spring.mvc.aop.log.service ..*.*(..))") public void ganagerLogPoint () {} @around ("gerenteLogPoint ()") Public Object OnroundroundManagerLogPoint (procedimiento JP). }} AroundManagerLogPoint: el principal proceso comercial del método principal
1. Compruebe si la clase del método de interceptación está anotada por @Logenable. Si es así, se seguirá la lógica de registro, de lo contrario se ejecutará la lógica normal.
2. Verifique si el método de intercepción es @LogEvent. Si es así, se seguirá la lógica de registro, de lo contrario, se ejecutará la lógica normal.
3. Obtenga el valor medio de @LogEvent en función del método de obtención y genere algunos parámetros del registro. El valor de @LogEvent se define en la clase como el valor predeterminado
4. Llame al proceso de Loginfogeneration de ManagerLogMessage para llenar otros parámetros en el registro. Hablaremos de este método más tarde.
5. Realizar llamadas comerciales normales
6. Si la ejecución es exitosa, el logManager ejecuta el registro (solo registramos los registros de ejecución exitosa aquí, y también puede definir los registros de grabación fallida)
@Around ("ManagerLogPoint ()") Objeto público alrededor de ManagerLogPoint (procedimientoJoinPoint JP) lanza Throwable {class Target = JP.GetTarget (). GetClass (); // Obtener logenable logenable logenable = (logenable) target.getAnnotation (logenable.class); if (logenable == null ||! logenable.logenable ()) {return jp.proced (); } // Obtenga LogEvent en la clase como el valor predeterminado logEvent LogEventClass = (LogEvent) Target.getAnnotation (logevent.class); Método método = getInvokedmethod (jp); if (método == null) {return jp.proceed (); } // Obtenga logEvent en el método logEvent logeVentMethod = método.getAnnotation (logevent.class); if (logEventMethod == null) {return jp.proced (); } String optevent = logeVentMethod.event (). GetEvent (); String optModel = logeVentMethod.module (). GetModule (); Cadena desc = logeventmethod.desc (); if (logeventClass! = null) {// Si el valor en el método es el valor predeterminado, reemplácelo con el valor global. optevent = optevent.equals (eventtype.default)? logeventClass.event (). getEvent (): optevent; OPTMODEL = OPTMODEL.Equals (moduleType.default)? LogEventClass.Module (). GetModule (): OptModel; } Logadmmodel logBean = new LogadMmodel (); LogBean.SetAdmmodel (OptModel); LogBean.SetAdMevent (Optevent); LogBean.SetDesc (DESC); logBean.setCreateDate (nueva fecha ()); Loginfogeneration.ProcessingManagerLogMessage (JP, LogBean, Método); Objeto returnObj = jp.proced (); if (optevent.equals (eventtype.login)) {// toDo Si se inicia sesión, debe juzgar si es exitoso en función del valor de retorno. Si es exitoso, agregue registros. El juicio aquí es relativamente simple if (returnObj! = Null) {this.logmanager.deallog (logBean); }} else {this.logmanager.dealLog (logBean); } return returnObj; } / ** * Obtenga el método de solicitud * * @param jp * @return * / public método getInvokedmethod (unkenpoint jp) {// parámetros de la lista de métodos de llamada classList = new ArrayList (); for (objeto obj: jp.getArgs ()) {classList.Add (obj.getClass ()); } Class [] argscls = (class []) classList.ToArray (nueva clase [0]); // El nombre de método llamado String MethodName = jp.getSignature (). GetName (); Método método = nulo; intente {método = jp.getTarget (). getClass (). getMethod (MethodName, argSCLS); } catch (nosuchmethodexception e) {E.PrintStackTrace (); } método de retorno; }}6. La solución para aplicar la solución anterior en la práctica
Aquí simulamos el negocio de los estudiantes y utilizamos las anotaciones anteriores para aplicarlas e interceptar los registros.
6.1. Istudentservice
Clase de interfaz comercial, ejecutar General Crud
interfaz pública istudentService {void deletyById (ID de cadena, cadena a); int save (StudentModel StudentModel); Actualización vacía (StudentModel StudentModel); vacío QueryById (ID de cadena);}6.2. StudentserviceImpl:
@Logenable: @LogEvent Define todos los métodos del módulo en la clase de intercepción de registro de inicio. Otra información sobre @Logeven define el registro. @Servicio @logenable // iniciar la intercepción de registro @LogeVent (module = moduleType.student) public class StudentserviceImpl implementa istudentService {@Override @LogEvent (eventType.delete_sEntle, desc = "delete registro") // Agregar logaro público System.out.printf (this.getClass () + "deletyById id =" + id); } @Override @LoGEvent (event = eventType.add, desc = "Save Record") // Agregar identificador de registro public int save (StudentModel StudentModel) {System.out.printf (this.getClass () + "Save Save =" + Json.ToJSonstring (StudentModel)); regresar 1; } @Override @LoGEvent (event = eventType.update, desc = "actualizar registro") // Agregar identificador de registro de la actualización public void (StudentModel StudentModel) {System.out.printf (this.getClass () + "Save Update =" + JSON.ToJSonstring (StudentModel)); } // sin identificador de registro @Override public void queryById (ID de cadena) {System.out.printf (this.getClass () + "QueryById id =" + id); }}Ejecute la clase de prueba e imprima la siguiente información para indicar que nuestra configuración de anotación de registro está habilitada:
Almacene los registros en la base de datos, y el contenido de registro es el siguiente:
{"Admevent": "4", "AdmModel": "1", "AdmoptContent": "{/" id/":/" 1/"}", "creó": 1525779738111, "DESC": "Delete Record"}}}}}}7. Código
Consulte a continuación el código detallado anterior
Código GitHub, intente usar la etiqueta V0.21, no use el maestro, porque no puedo garantizar que el código maestro permanezca sin cambios