三種動態代理方式

一、建立Interface java

 

 
public interface IUserDao {  
    void save();  
}  

 


二、建立實現類spring

 

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

 

  


三、建立靜態代理編程

 

 
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("我是靜態代理,關閉前");  
    }  
      
}  

 


四、建立動態代理ide

//給全部的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;  
            }  
        });  
    }  
}  

 


五、建立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;  
    }  
      
      
}  

 


六、建立測試類工具

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代理對象,關閉事務this

相關文章
相關標籤/搜索