## 一、為什么要使用動態代理
當一個對象或多個對象實現了N中方法的時候,由于業務需求需要把這個對象和多個對象的N個方法加入一個共同的方法,比如把所有對象的所有方法加入事務這個時候有三種方法:
方法一:一個一個對象一個一個方法去加,很顯然這個方法是一個比較笨的方法。
方法二:加一個靜態代理對象將這個靜態代理對象實現要加事務對象的接口。然后在靜態代理對象里面每個方法里面加上事務。
方法三:使用動態代理對象,進行動態的加載事務。
使用動態代理是為了讓對象實現了開閉原則,對擴展開放,而對修改關閉。Spring的AOP其實就是用了動態代理+IoC容器實現的
二、代碼實現。> ? ? ? ? UserManger.java接口
~~~
package com.tgb.spring;
public interface UserManager {
public void addUser(String username,String password);
public void delUser(int userId);
public String findUserById(int userId);
public void modifyUser(int userId,String username,String password);
}
~~~
方法一 常規的做法:
UserMangerImpl.Java
~~~
package com.tgb.spring;
public class UserManagerImpl implements UserManager {
public void addUser(String username, String password) {
checkSecurity();
System.out.println("UserManager.addUser");
}
public void delUser(int userId) {
checkSecurity();
System.out.println("UserManager.delUser");
}
public String findUserById(int userId) {
checkSecurity();
System.out.println("UserManager.findUserById");
return "張三";
}
public void modifyUser(int userId, String username, String password) {
checkSecurity();
System.out.println("UserManager.modifyUser");
}
private void checkSecurity(){
System.out.println("checkSecurity");
}
}
~~~
Client.java
~~~
package com.tgb.spring;
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
UserManager userManager=new UserManagerImpl();
userManager.addUser("11", "1231");
}
}
~~~
方法二 靜態代理:
UserManagerImpl.java
~~~
package com.tgb.spring;
public class UserManagerImpl implements UserManager {
public void addUser(String username, String password) {
//checkSecurity();
System.out.println("UserManager.addUser");
}
public void delUser(int userId) {
//checkSecurity();
System.out.println("UserManager.delUser");
}
public String findUserById(int userId) {
//checkSecurity();
System.out.println("UserManager.findUserById");
return "張三";
}
public void modifyUser(int userId, String username, String password) {
//checkSecurity();
System.out.println("UserManager.modifyUser");
}
// private void checkSecurity(){
// System.out.println("checkSecurity");
//
// }
}
~~~
UserManagerImplProxy.java
~~~
package com.tgb.spring;
public class UserManagerImplProxy implements UserManager {
private UserManager userManager;
public UserManagerImplProxy(UserManager userManager){
this.userManager=userManager;
}
public void addUser(String username, String password) {
// TODO Auto-generated method stub
checkSecurity();
userManager.addUser(username, password);
}
public void delUser(int userId) {
// TODO Auto-generated method stub
checkSecurity();
userManager.delUser(userId);
}
public String findUserById(int userId) {
// TODO Auto-generated method stub
checkSecurity();
return userManager.findUserById(userId);
}
public void modifyUser(int userId, String username, String password) {
// TODO Auto-generated method stub
checkSecurity();
userManager.modifyUser(userId, username, password);
}
private void checkSecurity(){
System.out.println("checkSecurity");
}
}
~~~
Client.java
~~~
package com.tgb.spring;
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
UserManagerImpl uesrMangerImpl=new UserManagerImpl();
UserManager userManager=new UserManagerImplProxy(uesrMangerImpl);
userManager.addUser("11", "1231");
}
}
~~~
方法三:動態代理
UserManagerImpl.java與方法二的UserManagerImpl.java一樣把UserManagerImplProxy.java刪除
新添一個類:
SecurityHandler.java
~~~
package com.tgb.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;
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(),
this);
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
checkSecurity();
//調用目標方法
Object ret=method.invoke(targetObject, args);
return ret;
}
private void checkSecurity(){
System.out.println("checkSecurity");
}
}
~~~
Client.java
~~~
package com.tgb.spring;
public class Client {
public static void main(String[] args) {
SecurityHandler handler=new SecurityHandler();
UserManager userManager=(UserManager)handler.createProxyInstance(new UserManagerImpl());
userManager.addUser("zha", "123");
}
}
~~~
三種方法的效果是一樣的如圖:

## 三、總結。
動態代理的利用給我們編碼帶來了很大的便利,解決了動態為對象提供服務的方案。動態代理+IoC容器的結合讓我們對系統提供服務更加的方便了這樣我們也就實現了開閉原則。這樣也就能實現了對象想要的時候就有不用的時候就撤出全心全意為開發者服務。
- 前言
- 菜鳥學習Struts——配置Struts環境
- 菜鳥學習Struts——簡易計算器
- 菜鳥學習Struts——bean標簽庫
- 菜鳥學習Struts——Scope屬性
- 菜鳥學習Struts——國際化
- 菜鳥學習Struts——總結
- 菜鳥學習Hibernate——配置Hibernate環境
- 菜鳥學習Hibernate——持久層框架
- 菜鳥學習Hibernate——簡單的一個例子
- 菜鳥學習Hibernate——簡單的增、刪、改、查操作
- 菜鳥學習Hibernate——一對多關系映射
- 菜鳥學習Hibernate——多對多關系映射
- 菜鳥學習Hibernate——緩存
- 菜鳥學習Spring——初識Spring
- 菜鳥學習Spring——第一個例子
- 菜鳥學習Spring——60s讓你學會動態代理原理
- 菜鳥學習Spring——60s使用annotation實現簡單AOP
- 菜鳥學習Spring——60s配置XML方法實現簡單AOP
- 菜鳥學習Spring——60s利用JoinPoint獲取參數的值和方法名稱
- 菜鳥學習Spring——60s學會Spring與Hibernate的集成
- 菜鳥學習SSH——目錄
- 菜鳥學習Spring——SpringMVC注解版前臺向后臺傳值的兩種方式
- 菜鳥學習Spring——SpringMVC注解版在服務器端獲取Json字符串并解析
- 菜鳥學習Spring——SpringMVC注解版將URL中的參數轉成實體
- 菜鳥學習Spring——SpringMVC注解版解析不同格式的JSON串
- 菜鳥學習Spring——SpringIoC容器基于三種配置的對比