什么是AOP我們先來(lái)看一張圖
圖中A就是通知,比如你要給每個(gè)方法前都加一個(gè)before()
方法,目標(biāo)類(lèi)的每一個(gè)方法叫joinpoint(切入點(diǎn)),每個(gè)切入點(diǎn)都會(huì)用到通知,把通知和切入點(diǎn)連起來(lái),點(diǎn)成線,線成面,這就是切面,也就是AOP,下面我們來(lái)簡(jiǎn)單寫(xiě)個(gè)小例子來(lái)實(shí)現(xiàn)一下
目標(biāo)類(lèi)的接口
public interface UserService { public void addUser() ; public void updateUser(); public void deleteUser(); }
目標(biāo)類(lèi)接口的實(shí)現(xiàn)
public class UserServiceImpl implements UserService { @Override public void addUser() { System.out.println("addUser"); } @Override public void updateUser() { System.out.println("updateUser"); } @Override public void deleteUser() { System.out.println("deleteUser"); } }
通知類(lèi)
public class MyAspect { public void before(){ System.out.println("before"); } public void after(){ System.out.println("after"); } }
代理類(lèi)
public class MyBeanFactory { public static UserService createService(){ //1.目標(biāo)類(lèi) final UserService userService = new UserServiceImpl() ; //2.切面類(lèi) final MyAspect myAspect = new MyAspect(); // 切入點(diǎn)和切面類(lèi)結(jié)合 // 三個(gè)參數(shù) // 1. loader ,類(lèi)加載器 運(yùn)行是加載,用類(lèi)加載器將其加載到內(nèi)存 // 2. interfaces 代理類(lèi)需要實(shí)現(xiàn)的所有接口 // 3. invocationHandler 處理類(lèi),一般采用匿名內(nèi)部類(lèi) // 提供了invoke方法 代理類(lèi)每個(gè)方法執(zhí)行時(shí)都將調(diào)用一次invoke ,又有三個(gè)參數(shù) // 1. Object proxy 代理對(duì)象 // 2. Method method 代理對(duì)象方法的反射 // 3. Object[] args 方法的實(shí)際參數(shù) UserService proxyService = (UserService) Proxy.newProxyInstance(MyBeanFactory.class.getClassLoader(), userService.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println(method.getName()); myAspect.before(); Object obj = method.invoke(userService, args); myAspect.after(); return obj ; } }); return proxyService ; } }
測(cè)試類(lèi)
public class UserServiceImplTest { @org.junit.jupiter.api.Test public void demo() throws Exception { UserService userService = MyBeanFactory.createService(); userService.addUser(); userService.deleteUser(); userService.updateUser(); } }
結(jié)果
addUser
before
addUser
after
deleteUser
before
deleteUser
after
updateUser
before
updateUser
after
Process finished with exit code 0
我們可以看到每個(gè)方法都執(zhí)行了通知,用了動(dòng)態(tài)代理就不用手動(dòng)的給每個(gè)方法前后加入通知,這樣既節(jié)省了時(shí)間,也保證了主體代碼不被改變
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)服務(wù)器之家的支持。