三種動態代理方式


1、創建Interface 

 

 
public interface IUserDao {  
    void save();  
}  

 


2、創建實現類

 

 
public class UserDao implements IUserDao {  
  
    @Override  
    public void save() {  
        // TODO Auto-generated method stub  
        System.out.println("我是原始方法,不要改變我哈");  
    }  
  
}

 

  


3、創建靜態代理

 

 
public class UserDaoStaticProxy  implements IUserDao{  
    private IUserDao userDao;  
    public UserDaoStaticProxy (IUserDao userDao) {  
        this.userDao = userDao;  
    }  
    @Override  
    public void save() {  
        // TODO Auto-generated method stub  
        System.out.println("我是靜態代理,啟動前");  
        this.userDao.save();  
        System.out.println("我是靜態代理,關閉前");  
    }  
      
}  

 


4、創建動態代理

//給所有的dao創建動態代理對象  
  
public class UserDaoDynamicProxy {  
    //維護一個目標對象  
    private Object targetObject;  
    public UserDaoDynamicProxy(Object target){  
        this.targetObject = target;  
    }  
    public Object getProxyInstance(){  
        return Proxy.newProxyInstance(  
                targetObject.getClass().getClassLoader(),  
                targetObject.getClass().getInterfaces(),   
                new InvocationHandler() {  
              
            @Override  
            public Object invoke(Object proxy, Method method, Object[] args)  
                    throws Throwable {  
                // TODO Auto-generated method stub  
                System.out.println("我是動態代理,開啟事務");  
                  
                //執行目標對象方法  
                Object returnValue = method.invoke(targetObject, args);  
                  
                System.out.println("我是動態代理,關閉事務");  
                return returnValue;  
            }  
        });  
    }  
}  

 


5、創建Cglib代理

 

public class UserDaoCglibProxy implements MethodInterceptor{  
    //維護目標對象  
    private Object targetObject;  
    public UserDaoCglibProxy(Object target){  
        this.targetObject = target;  
    }  
      
    //給目標對象創建代理對象  
    public Object getProxyInstance(){  
        //工具類  
        Enhancer enhancer = new Enhancer();  
        //設置父類  
        enhancer.setSuperclass(targetObject.getClass());  
        //設置回調函數  
        enhancer.setCallback(this);  
        //創建子類  
        return enhancer.create();  
    }  
      
    @Override  
    public Object intercept(Object obj, Method method, Object[] args,  
            MethodProxy arg3) throws Throwable {  
        System.out.println("我是CGLIB代理對象,啟動事務");  
        Object returnValueObject = method.invoke(targetObject, args);  
        System.out.println("我是CGLIB代理對象,關閉事務");  
        return returnValueObject;  
    }  
      
      
}  

 


6、創建測試類

public class App {  
  
    public static void main(String[] args) {  
        // TODO Auto-generated method stub  
        IUserDao userDao = new UserDao();  
        //靜態代理對象  
//      1)可以做到在不修改目標對象的功能前提下,對目標對象功能擴展。  
//      2)缺點:  
//          --》  因為代理對象,需要與目標對象實現一樣的接口。所以會有很多代理類,類太多。  
//          --》  一旦接口增加方法,目標對象與代理對象都要維護。  
        UserDaoStaticProxy proxy = new UserDaoStaticProxy(userDao);  
        proxy.save();  
          
        System.out.println("\n------------------------\n");  
        //動態代理對象  
//      1)代理對象,不需要實現接口;  
//      2)代理對象的生成,是利用JDKAPI, 動態的在內存中構建代理對象(需要我們指定創建 代理對象/目標對象 實現的接口的類型;);  
//      3)  動態代理, JDK代理, 接口代理;  
//      代理對象不需要實現接口,但是目標對象一定要實現接口;否則不能用動態代理!  
//      static Object newProxyInstance(  
//              ClassLoader loader,       指定當前目標對象使用類加載器  
//               Class<?>[] interfaces,     目標對象實現的接口的類型  
//              InvocationHandler h       事件處理器  
//              )    
        IUserDao userDao2 = (IUserDao) new UserDaoDynamicProxy(userDao).getProxyInstance();  
        userDao2.save();  
          
        System.out.println("\n------------------------\n");  
        //Cglib代理,也叫做子類代理。在內存中構建一個子類對象從而實現對目標對象功能的擴展。  
//      JDK的動態代理有一個限制,就是使用動態代理的對象必須實現一個或多個接口。如果想代理沒有實現接口的類,就可以使用CGLIB實現。  
//      1) 需要引入cglib – jar文件, 但是spring的核心包中已經包括了cglib功能,所以直接引入spring-core-3.2.5.jar即可。  
//      2)引入功能包后,就可以在內存中動態構建子類  
//      3)代理的類不能為final, 否則報錯。  
//      4) 目標對象的方法如果為final/static, 那么就不會被攔截,即不會執行目標對象額外的業務方法  
        IUserDao userDao3 = (IUserDao) new UserDaoCglibProxy(userDao).getProxyInstance();  
        userDao3.save();  
        //總結  
//      在Spring的AOP編程中,  
//      如果加入容器的目標對象有實現接口,用JDK代理;  
//      如果目標對象沒有實現接口,用Cglib代理;  
  
    }  
  
}  

 

打印結果:

 

我是靜態代理,啟動前
我是原始方法,不要改變我哈
我是靜態代理,關閉前

------------------------

我是動態代理,開啟事務
我是原始方法,不要改變我哈
我是動態代理,關閉事務

------------------------

我是CGLIB代理對象,啟動事務
我是原始方法,不要改變我哈
我是CGLIB代理對象,關閉事務


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM