前言java
爲何要再談,由於動態代理是aop編程的核心。後面分析spring aop的源代碼的最重要的理論基礎。spring
再談動態代理編程
首先動態代理須要哪些角色呢?ide
1.抽象角色。這個抽象角色必須爲接口。函數
2.具體角色。這個具體角色必須實現抽象接口。this
3.IAdvice接口和BeforeAdviceImple實現類。spa
4.InvocationHandler的實現類。這個類爲動態代理的Handler類。設計
5.產生代理的接口,抽象類,工廠類。代理
6.場景類Client。code
1.咱們先新增一個抽象角色ISubject接口。這個接口定義一個方法handle。代碼以下所示:
1 package com.example.pattern.proxy.dynamic.second; 2 3 public interface ISubject { 4 5 public void handle(); 6 }
第5行,定義接口handle。
2.定義一個具體角色RealSubject。這個角色實現ISubject接口。代碼以下所示:
1 package com.example.pattern.proxy.dynamic.second; 2 3 public class RealSubject implements ISubject { 4 @Override 5 public void handle() { 6 System.out.println("-----handle-----"); 7 } 8 }
第6行,處理handle業務邏輯。
3.新增一個通知事件的接口和實現類,代碼以下所示。
1 package com.example.pattern.proxy.dynamic.second; 2 3 public interface IAdvice { 4 5 public void execute(); 6 }
1 package com.example.pattern.proxy.dynamic.second; 2 3 public class BeforeAdviceImpl implements IAdvice { 4 @Override 5 public void execute() { 6 System.out.println("執行前置通知"); 7 } 8 }
第6行,定義execute業務前置邏輯。
4.再來新增一個InvocationHandler的默認處理器。
1 package com.example.pattern.proxy.dynamic.second; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Method; 5 6 public class DefaultInvocationHandler implements InvocationHandler { 7 8 private Object instance = null; 9 10 public DefaultInvocationHandler(Object instance) { 11 this.instance = instance; 12 } 13 14 @Override 15 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 16 return method.invoke(this.instance, args); 17 } 18 }
第8行,定義被代理對象的實例。
5.產生代理的接口,抽象類,實現類。
1 package com.example.pattern.proxy.dynamic.second; 2 3 import java.lang.reflect.InvocationHandler; 4 5 public interface IDynamicProxy<T> { 6 7 public <T> T newProxyInstace(Class<T> clazz, InvocationHandler h); 8 9 }
package com.example.pattern.proxy.dynamic.second; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; public abstract class AbstractDynamixProxy<T> implements IDynamicProxy<T> { public abstract void before() ; @Override public T newProxyInstace(Class clazz, InvocationHandler h) { this.before(); ClassLoader classLoader = clazz.getClassLoader(); Class[] interfaces = clazz.getInterfaces(); return (T)Proxy.newProxyInstance(classLoader, interfaces, h); } }
1 package com.example.pattern.proxy.dynamic.second; 2 3 public class SubjectDynamicProxyImpl<ISubject> extends AbstractDynamixProxy<ISubject>{ 4 5 @Override 6 public void before() { 7 8 IAdvice advice = new BeforeAdviceImpl(); 9 advice.execute(); 10 11 } 12 }
①有接口,有抽象類,有具體方法?我爲何要這麼設計呢?爲何不是直接寫在場景類中呢?那若是有10個場景須要,是否是在10出都要寫相同或者類似的代碼呢?若是一旦有改動,那麼,改動的工做量不說,容易產生潛伏性bug。 接口是聲明主要用途,抽象類是用來提取公共代碼。具體類是爲了構建個性化代碼,好比before方法。 就是一個典型的鉤子函數。說了這麼多,這難道不是模板模式的應用嗎?
②IDynamicProxy<T>這是一個泛型接口。T能夠是一個接口或者普通類,具體是什麼類型,由場景來類決定,這不就實現了代碼很是靈活的複用嗎?同時不也是提升了可讀性嗎?
6.增長場景類Client。
1 public class Client { 2 3 public static void main(String[] args) { 4 ISubject subject = new RealSubject(); 5 6 InvocationHandler invocationHandler = new DefaultInvocationHandler(subject); 7 8 IDynamicProxy<ISubject> dynamicProxy = new SubjectDynamicProxyImpl(); 9 ISubject proxyInstance = dynamicProxy.newProxyInstace(subject.getClass(), invocationHandler); 10 11 proxyInstance.handle(); 12 } 13 }
執行的結果以下圖所示:
1 執行前置通知 2 -----handle-----
咱們爲何要使用IAdvice呢。這已經引入了aop中的一些術語,在什麼地方執行什麼行爲,是否是能夠理解 在鏈接點執行什麼通知呢?這已是一個簡單的面向切面過程的示例,Advice是什麼呢?也正是咱們要去切入的類。