JAVA動態代理是通過反射機制,創建了代理接口的匿名類,在調用具體方法前調用InvokeHandler來處理,然後才採用具體當前接口的具體實現類的業務邏輯。
JAVA動態代理原理如下圖所示:
Jdk的動態代理要求目標對象必須實現接口,因爲它創建代理對象的時候是根據接口創建的。如果不實現接口,jdk無法給目標對象創建代理對象。被代理對象可以可以實現多個接口,創建代理時指定創建某個接口的代理對象就可以調用該接口定義的方法了。
示例代碼:
1、定義第一個接口:
public interface Service {
public void sayHello(String name);
public int addOperter(int num,int num2);
}
2、定義第二個接口:
public interface UserService {
public void addUser(String userId, String userName) ;
public void delUser(String userId);
public void modfiyUser(String userId, String userName);
public String findUser(String userId);
}
3、定義實現類:
public class UserServiceImpl implements Service,UserService{
@Override
public void addUser(String userId, String userName) {
System.out.println("UserServiceImpl addUser userId->>"+userId);
}
@Override
public void delUser(String userId) {
System.out.println("UserServiceImpl delUser userId->>"+userId);
}
@Override
public void modfiyUser(String userId, String userName) {
System.out.println("UserServiceImpl modfiyUser userId->>"+userId);
}
@Override
public String findUser(String userId) {
System.out.println("UserServiceImpl findUser userId->>"+userId);
return "張山";
}
@Override
public void sayHello(String name) {
System.out.println("你好:"+name);
}
@Override
public int addOperter(int num, int num2) {
return num+num2;
}
}
4、編寫aspect
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class LogHandler implements InvocationHandler {
private Object targertObject;
public Object newInstance(Object targertObject){
this.targertObject = targertObject;
Class targertClass = targertObject.getClass();
return Proxy.newProxyInstance(targertClass.getClassLoader(), targertClass.getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("調用方法"+method.getName());
Object ret = null;
try {
ret = method.invoke(targertObject, args);
System.out.print("成功調用方法:"+method.getName()+";參數爲:");
for (int i = 0; i < args.length; i++) {
System.out.println(args[i]);
}
} catch (Exception e) {
e.printStackTrace();
System.out.print("調用方法:"+method.getName()+"失敗;參數爲:");
for (int i = 0; i < args.length; i++) {
System.out.print(args[i]);
}
}
return ret;
}
}
5、編寫測試類:
Service Service = (Service)new LogHandler().newInstance(new UserServiceImpl());
UserService userService = (UserService)new LogHandler().newInstance(new UserServiceImpl());
userService.addUser("001", "centre");
String name = userService.findUser("002");
System.out.println(name);
int num = Service.addOperter(12, 23);
System.out.println(num);
Service.sayHello("centre");
測試結果:
調用方法addUser
UserServiceImpl addUser userId->>001
成功調用方法:addUser;參數爲:001
centre
調用方法findUser
UserServiceImpl findUser userId->>002
成功調用方法:findUser;參數爲:002
張山
調用方法addOperter
成功調用方法:addOperter;參數爲:12
23
35
調用方法sayHello
你好:centre
成功調用方法:sayHello;參數爲:centre