動態代理:
根據目標對象,在程序運行期自動裝配目標對象的代理對象.
優點:可以根據不同的對象,動態裝配出對應的代理對象
缺點:采用了反射,導致運行速度會有延遲,JDK的動態代理必須是實現了接口的類(如果不實現接口,可以使用CGLIB)
接口類:UserManager.java
package com.linuxidc.spring; public interface UserManager { public void addUser(String username, String password); }
實現類:UserManagerImpl.java
package com.linuxidc.spring; public class UserManagerImpl implements UserManager { @Override public void addUser(String username, String password) { System.out.println("--------UserManagerImpl.addUser()-----------------"); } }
動態代理類:UserManagerImplProxy.java
package com.bjpowernode.spring; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class SecurityHandler implements InvocationHandler { private Object targetObject; //傳入目標對象 public Object createProxyInstance(Object targetObject){ this.targetObject = targetObject; //加載目標的裝載器,目標實現的接口,實現了InvocationHandler的類的對象,會調用對象的invoke方法,並返回代理this(jvm虛擬機中自動裝配) //已經知道目標的實現的接口,動態創建出目標的一個代理類的對象(this)並返回 //實現了InvocationHandler的類的對象,會調用對象的invoke方法 //根據method拿到對象的當前方法 return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object rect = null; //根據規則,只對add開始的方法代理,類型與Spring中代理實現(Pointcut,Advice) if(method.getName().startsWith("add123")){ checkScurity(); //method.invoke()取得對象執行的某個方法並執行該方法 rect = method.invoke(targetObject, args); } return rect; } private void checkScurity(){ System.out.println("------------checkScurity----------"); } }
測試類:Client.java
package com.linuxidc.spring; public class Client { /** * @param args */ public static void main(String[] args) { // UserManager userManager = new UserManagerImpl(); UserManagerImplProxy proxy = new UserManagerImplProxy(); UserManager userManager = (UserManager) proxy.createObjectProxy(new UserManagerImpl()); userManager.addUser("張三", "123456"); } }