AOP面向切面编程:由动态代理的方式去执行业务类方法。将业务类以参数的形式传入代理类,然后代理类返回一个业务类的对象。此时返回的对象不管执行什么方法,都会直接去执行代理类的invoke方法。一般实现在invoke方法中去调用该业务类的方法。从而达到面向切面编程(方法前方法后都会有方法执行)。
1.业务类
package com.mr.li.test.aop; public interface HelloService { void sayHello(String name); }
package com.mr.li.test.aop; public class HelloServiceImpl implements HelloService { @Override public void sayHello(String name) { if(name == null || name.trim() == "") { throw new RuntimeException("参数为null"); } System.out.println("hello " + name); } }
2.过滤器(自己写的,用于在方法前方法后执行,将其传入到代理类中然后在invoke方法中编辑执行)
package com.mr.li.test.aop; import java.lang.reflect.InvocationTargetException; /** * * @describe 拦截器 * * @author li.yanlong@icjhd.com * * @date 2021-8-26 11:47:33 */ public interface Interceptor { /** 方法前执行的方法 */ boolean before(); /** 方法后执行的方法 */ void after(); /** 取代原有事件方法, 通过invocation回调参数,可以通过他的proceed方法回调原事件 */ Object around(Invocation invocation) throws InvocationTargetException, IllegalAccessException; /** 是否返回方法,事件没有发生异常执行 */ void afterReturning(); /** 事后异常方法,当事件发生异常后执行 */ void afterThrowing(); /** 是否使用around方法取代原有方法 */ boolean useAround(); }
package com.mr.li.test.aop; import java.lang.reflect.InvocationTargetException; public class MyInterceptor implements Interceptor { @Override public boolean before() { System.out.println("方法执行前执行~~~before"); return false; } @Override public void after() { System.out.println("方法执行后执行~~~~after"); } @Override public Object around(Invocation invocation) throws InvocationTargetException, IllegalAccessException { System.out.println("代理方法执行~~~~around"); Object obj = invocation.proceed(); return obj; } @Override public void afterReturning() { System.out.println("方法没有发生异常时正常执行~~~~~~afterReturning"); } @Override public void afterThrowing() { System.out.println("当方法发生异常时执行~~~~~~~afterThrowing"); } @Override public boolean useAround() { System.out.println("是否使用around方法取代原有方法 执行~~~~~useAround 返回true"); return true; } }
3.代理类的参数对象
package com.mr.li.test.aop; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * * @describe 代理对象执行方法 * * @author li.yanlong@icjhd.com * * @date 2021-8-26 18:28:59 */ public class Invocation { private Object[] parame; private Method method; private Object target; public Invocation(Object[] parame, Method method, Object target) { this.parame = parame; this.method = method; this.target = target; } //以反射的方式调用方法 public Object proceed() throws InvocationTargetException, IllegalAccessException{ return method.invoke(target, parame);//target调用该方法的对象, parame:调用该方法的参数 } }
4.代理类:表示将业务类传进来,然后返回一个对象,该对象就是业务类的对象,然后该对象在转成具体的对象,此时只要执行该对象的方法,就会执行代理类的invoke,
package com.mr.li.test.aop; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ProxyBean implements InvocationHandler { private Object target = null; private Interceptor interceptor = null; @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { boolean exceptionFlag = false; Invocation invocation = new Invocation(args, method, target); Object retObj = null; try { if(this.interceptor.before()) { retObj = this.interceptor.around(invocation); }else { retObj = method.invoke(target, args); } } catch (Exception e) { exceptionFlag = true; } this.interceptor.after(); if(exceptionFlag) { this.interceptor.afterThrowing(); }else { this.interceptor.afterReturning(); return retObj; } return null; } public static Object getProxyBean(Object target, Interceptor interceptor) { ProxyBean proxyBean = new ProxyBean(); proxyBean.target = target; proxyBean.interceptor = interceptor; Object proxy = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), proxyBean); return proxy; } }
5.测试
package com.mr.li.test.aop; public class Test { public static void main(String[] args) { HelloService helloService = new HelloServiceImpl(); HelloService proxy = (HelloService)ProxyBean.getProxyBean(helloService, new MyInterceptor()); proxy.sayHello("哈哈哈"); System.out.println("------------------------------------------------"); proxy.sayHello(null); } }
测试结果:
方法执行前执行~~~before
hello 哈哈哈
方法执行后执行~~~~after
方法没有发生异常时正常执行~~~~~~afterReturning
------------------------------------------------
方法执行前执行~~~before
方法执行后执行~~~~after
当方法发生异常时执行~~~~~~~afterThrowing