說明
jdk動态代理就是對“裝飾者”設計模式的簡化。使用前提:必須要有接口
編寫過程:
1.目标類:接口+實作類
2.切面類:用于存放通知。
3.工廠類:編寫工廠生成代理
4.測試
UserService 接口 三個方法
public interface UserService {
public void addUser();
public void updateUser();
public void deleteUser();
}
UserService 實作類,實作了三個方法
public class UserServiceImpl implements UserService
@Override
public void addUser() {
System.out.println("UserServiceDaoImpl addUser");
}
@Override
public void updateUser() {
System.out.println("UserServiceDaoImpl updateUser");
}
@Override
public void deleteUser() {
System.out.println("UserServiceDaoImpl deleteUser");
}
}
切面類,共兩個方法,before和end。希望在目标類的方法運作前後各調用一次。
public class MyAspect {
public void before(){
System.out.println("before");
}
public void after(){
System.out.println("after");
}
}
工廠類,用于生成代理。
其中代理類的作用就是将目标類(切入點)和切面類(通知)結合。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class MyProxyFactory
public static Object createUserService() {
//目标類
final UserService userServiceDao = new UserServiceImpl();
//切面類
final MyAspect myAspect = new MyAspect();
//代理類
Object proxy = Proxy.newProxyInstance(MyProxyFactory.class
.getClassLoader(), userServiceDao.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
Object obj = null;
//前方法
myAspect.before();
//執行目标類的方法
obj = method.invoke(userServiceDao, args);
//後方法
myAspect.after();
return obj;
}
});
return
其中Proxy.newProxyInstance有三個參數。
- arg1:loader,類加載器,動态代理類,運作時建立,任何類都需要類加載器加載到記憶體。一般使用目前類.class.getClassLoader();也可以使用目标執行個體.getClass().getClassLoader()
- arg2:代理類要實作的所有接口。目标類例.getClass().getInterfaces();
- arg3:InvocationHandler處理類,接口必須進行實作。一般采用匿名内部實作。提供的invoke方法。代理類的每一個方法執行都會調用一次invoke。invoke也有三個參數(Object proxy:代理對象, Method method:代理對象目前執行的方法,Object[] args:目前執行方法的參數)。我們可以通過method.getName來為不同的方法實作不同的功能。
測試類
public class Test {
@org.junit.Test
public void testProxy(){
UserService userService=(UserService) MyProxyFactory.createUserService();
userService.addUser();
userService.updateUser();
userService.deleteUser();
}
}
運作結果
我們可以看到雖然我們調用的UserService對象,但是在每個方法執行的前後都有輸出before和after。是以我們使用工廠類實作了jdk動态代理。
我們其實可以這樣了解jdk動态代理。
在底層我們在調用代理類的方法時,它會執行invoke方法。
代理類本身沒有什麼功能,它隻是把所有的功能組合在一起。
代理類
addUser(){
invoke(this,addUser,[]);
}
updateUser(){
invoke(this,updateUser,[]);
}
deleteUser(){
invoke(this,deleteUser,[]);
}
你看懂了嗎?
上面說了 我們可以通過method.getName來為特定的方法實作特定的功能。那麼我們隻為addUser方法執行before和after方法。
我們修改代理類的invoke方法
@Override
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
Object obj = null;
if("addUser".equals(method.getName())){
//前方法
myAspect.before();
//執行目标類的方法
obj = method.invoke(userServiceDao, args);
//後方法
myAspect.after();
}else{
obj = method.invoke(userServiceDao, args);
}
return