代理顧名思義:代爲處理。不是對目標對象的直接操做,而是經過代理對目標對象進行包裝,此時能夠在目標對象的基礎上添加額外的操做以知足業務需求。圖示編程
分類:動態代理、靜態代理。ide
代理三要素:共同接口、真實對象、代理對象性能
引入代理的緣由:this
在某些狀況下,一個客戶不想或者不能直接引用另外一個對象,而代理對象能夠在客戶端和目標對象之間起到中介的做用【解耦】。 spa
public interface Action { public void doSomething(); } public class Proxyc implements Action{ Action realObject; public Proxyc(Action action) { realObject = action; } @Override public void doSomething() { System.out.println("被攔截前..."); realObject.doSomething(); System.out.println("被攔截後..."); } public static void main(String[] args) { Proxyc proxy = new Proxyc(new RealObject()); proxy.doSomething(); } }
優勢:擴展原功能,不侵入代碼代理
缺點:假若有10個不一樣的實際對象,對應10個不一樣的方法,該如何寫呢?日誌
1) 要麼建立不一樣的代理類,代理後這樣:code
proxy.doSomething()
proxy2.doSomething2()
proxy3.doSomething3()
...
問題:建立多個功能相似的代理類,僅傳入的真實對象不一樣orm
2) 要麼建立一個代理,實現不一樣的接口:對象
proxy.doSomething()
proxy.doSomething2()
proxy.doSomething3()
...
問題:代理類不斷膨脹
代理由靜態轉爲靜態源於靜態代理引入的額外工做。
動態代理就是咱們上面提到的方案一,只不過這些proxy的建立都是自動的而且是在運行期生成的。
不少繁瑣的編程能夠用動態代理解決
實現方式
反射方式舉例
public interface Action { public void doSomething(); } public class RealObject implements Action{ @Override public void doSomething() { System.out.println("I'm RealObject~"); } } public class DynamicProxyHandler implements InvocationHandler { private Object realObject; public DynamicProxyHandler(Object realObject) { this.realObject = realObject; } @Override public Object invoke(Object object, Method method, Object[] args) { Object result = null; try { result = method.invoke(realObject, args); } catch (InvocationTargetException|IllegalAccessException e) { e.printStackTrace(); } return result; } public static void main(String[] args) { RealObject realObject = new RealObject(); Action action = (Action) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Action.class}, new DynamicProxyHandler(realObject)); action.doSomething(); } }
經過Proxy.newProxyInstance()生成代理對象,須要傳入3個參數:classLoader + 代理接口 + InvocationHandler實例,
其中InvocationHandler接口,該接口定義了一個invoke方法,proxy最是最終生成的一個代理實例,通常不會用到,參數method是被代理目標實例的某個具體的方法,經過它能夠發起目標實例方法的反射調用;參數args是經過被代理實例某一個方法的入參,在方法反射調用時候使用,經過代理將橫切邏輯代碼和業務類的代碼編織到了一塊兒。
日誌
監控
鑑權
......
切面編程,是對OOP(面向對象編程)的一種補充,解決OOP其對對於跨越不一樣類、對象,糾纏邏輯變現的不足
public interface Waiter { public void service(); } public class ManWaiter implements Waiter{ @Override public void service() { System.out.println("service..."); } }
public interface BeforeAdvice { public void before(); } public interface AfterAdvice { public void after(); }
@Getter @Setter public class ProxyFactory { Object target; BeforeAdvice beforeAdvice; AfterAdvice afterAdvice; public Object createProxy() { ClassLoader classLoader = this.getClass().getClassLoader(); Class[] interfaces = target.getClass().getInterfaces(); InvocationHandler invocationHandler = new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (beforeAdvice != null) { beforeAdvice.before(); } Object result = method.invoke(target, args); afterAdvice.after(); return result; } }; Object proxyObject = Proxy.newProxyInstance(classLoader, interfaces, invocationHandler); return proxyObject; } public static void main(String[] args) { ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.setTarget(new ManWaiter()); proxyFactory.setBeforeAdvice(new BeforeAdvice() { @Override public void before() { System.out.println("Before Service."); } }); proxyFactory.setAfterAdvice(new AfterAdvice() { @Override public void after() { System.out.println("After Service........."); } }); Waiter waiter = (Waiter)proxyFactory.createProxy(); waiter.service(); } }
public interface UserService { public void service(); } public class UserServiceImpl implements UserService{ @Override public void service() { System.out.println("In Service......."); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Service end."); } }
public class MethodPerformance { private long start; private long end; String serviceMethod; public MethodPerformance(String serviceMethod) { this.serviceMethod = serviceMethod; start = System.currentTimeMillis(); } public void printPerformance() { end = System.currentTimeMillis(); System.out.println(serviceMethod + " cost Time: " + (end - start)); } } public class PerformanceMonitor { public static ThreadLocal<MethodPerformance> performanceThreadLocal = new ThreadLocal<>(); public static void begin(String method) { System.out.println("Start monitor>>"); MethodPerformance methodPerformance = new MethodPerformance(method); performanceThreadLocal.set(methodPerformance); } public static void end() { System.out.println("End monitor."); performanceThreadLocal.get().printPerformance(); } }
public class PerformanceHandler implements InvocationHandler { Object target; public PerformanceHandler(Object object) { target = object; } @Override public Object invoke(Object proxy, Method method, Object[] args) { Object result = null; try { PerformanceMonitor.begin(target.getClass().getName() + ":" + method.getName()); result = method.invoke(target, args); PerformanceMonitor.end(); } catch (IllegalAccessException| InvocationTargetException e) { e.printStackTrace(); } return result; } public static void main(String[] args) { UserService userService = new UserServiceImpl(); ClassLoader classLoader = userService.getClass().getClassLoader(); Class[] interfaces = userService.getClass().getInterfaces(); InvocationHandler invocationHandler = new PerformanceHandler(userService); UserService obj = (UserService) Proxy.newProxyInstance(classLoader, interfaces, invocationHandler); obj.service(); } }