Spring5-(10)JDK動態(tài)代理

一.分析(必須要求真實對象是有接口的)

   1. java.lang.reflext.proxy 類:java 動態(tài)代理機(jī)制生成的所有動態(tài)代理類的父類,它提供了一組靜態(tài)方法為一組接口動態(tài)地生成代理類及其對象
   
    主要方法:public static Object newProxyInstance(ClassLoader loader, Class<?>[]interface, invocationHander hander)
    
    方法職責(zé):為指定類加載器,一組接口及調(diào)用處理器生成動態(tài)代理實例
    參數(shù)
    loader :類加載器,一般傳遞真實對象的加載器
    interface :代理類需要實現(xiàn)的接口
    hander:代理對象如何做增強(qiáng)
   返回:創(chuàng)建的代理對象
   
   2.java.lang.reflect.invocationHander接口:
   public invoke(Object proxy, Method method,Object[] args)
   
   方法職責(zé):負(fù)責(zé)集中處理動態(tài)代理類上的所有方法調(diào)用
   參數(shù):
   proxy:生成代理對象
   methos:當(dāng)前調(diào)用的真實方法對象
   args:當(dāng)前調(diào)用方法的實參
   返回:真實方法的返回結(jié)果n

二.JDK 動態(tài)代理操作步驟:

1.創(chuàng)建一個代理對象
2.實現(xiàn)invocationHander接口
3.覆蓋invoke(),為真實對象方法做增強(qiáng)的具體操作        

代碼演示:

package com.keen.proxy.tx;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
@SuppressWarnings("all")//忽略所有警告
public class TransactionManagerAdvice implements InvocationHandler{
    private Object targer;//真實對象,即對誰做增強(qiáng)
    private TransactionManager txManager;//事務(wù)管理器(模擬)
    
    public void setTarger(Object targer) {
        this.targer = targer;
    }
    public void setTxManager(TransactionManager txManager) {
        this.txManager = txManager;
    }
    
    //創(chuàng)建一個代理對象
    public <T> T getproxyObject() {
        return (T) Proxy.newProxyInstance(targer.getClass().getClassLoader(),//loader類加載器,一般跟上真實對象的類加載器
                
                targer.getClass().getInterfaces(),//真實對象所實現(xiàn)的接口(jdk動態(tài)代理必須要求真實對象有接口)
                
                this);//如何做事務(wù)增強(qiáng)的對象因為繼承了InvocationHandler,所以直接用this就可以了
    }
    @Override
    //如何為真實對象的方法增強(qiáng)的具體操作
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object ret = null;
        txManager.begin();
        //調(diào)用真實對象的方法
          try {
            ret = method.invoke(targer, args);//調(diào)用對象真實的方法
            txManager.commit();
        } catch (Exception e) {
            
            e.printStackTrace();
            txManager.rollback();
        }
        return ret;
    }
}

context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<!-- di注解解析器 -->
<!--  <context:annotation-config/> -->

<!--IOC注解解析器  -->
<!-- <context:component-scan base-package="com.keen.proxy"/> -->
<bean id = "employeeDAO" class = "com.keen.proxy.dao.EmployeeDAOimpl"/>

<!-- 事務(wù)管理器 -->
<bean id = "transactionManager" class = "com.keen.proxy.tx.TransactionManager"/>

<!-- 配置事務(wù)增強(qiáng)類 -->

<bean id = "transactionManagerAdvice" class = "com.keen.proxy.tx.TransactionManagerAdvice" >
  <property name="txManager" ref ="transactionManager"/>
  <property name="targer" >
    <!-- 把employeeService作為內(nèi)部bean -->
        <bean class ="com.keen.proxy.service.IEmployeeServiceImpl">
           <property name = "dao" ref = "employeeDAO"/>
        </bean>
  </property>
</bean>

</beans>


測試類

package com.keen.proxy;


import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;

import com.keen.proxy.domain.Employee;
import com.keen.proxy.service.IEmployeeService;
import com.keen.proxy.tx.TransactionManagerAdvice;

@SpringJUnitConfig
public class AutoTest {
    @Autowired 
    private TransactionManagerAdvice advice;
    
    
    @Test
    void testSave() throws Exception {
        //獲取代理對象 class com.sun.proxy.$Proxy19
         IEmployeeService service = advice.getproxyObject();
         service.save(new Employee());
    }
    @Test
    void testUpdate() throws Exception {
        IEmployeeService service = advice.getproxyObject();
         service.update(new Employee());
        
    }
    
}

??:其他涉及相關(guān)的類和上一篇靜態(tài)代理的類一樣的,只是動態(tài)代理不需要靜態(tài)代理那個IEmployeeServiceProxy類了。我們用TransactionManagerAdvice 替代了。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,680評論 19 139
  • Spring Web MVC Spring Web MVC 是包含在 Spring 框架中的 Web 框架,建立于...
    Hsinwong閱讀 22,966評論 1 92
  • 2016年12月30號,本年度最后一天個工作日,到處都是放假的氣氛,不能專心做事。 重新安裝了簡書客戶端,才意識到...
    忘念閱讀 249評論 0 0
  • 大年初一看了電影《紅海行動》,半個月前老公就嚷著說要陪他一起去看的電影,終于一睹為快了。 影片講述的是伊維亞共和國...
    慧慧2018閱讀 561評論 1 1

友情鏈接更多精彩內(nèi)容