Spring5-(10)JDK动态代理

一.分析(必须要求真实对象是有接口的)

   1. java.lang.reflext.proxy 类:java 动态代理机制生成的所有动态代理类的父类,它提供了一组静态方法为一组接口动态地生成代理类及其对象
   
    主要方法:public static Object newProxyInstance(ClassLoader loader, Class<?>[]interface, invocationHander hander)
    
    方法职责:为指定类加载器,一组接口及调用处理器生成动态代理实例
    参数
    loader :类加载器,一般传递真实对象的加载器
    interface :代理类需要实现的接口
    hander:代理对象如何做增强
   返回:创建的代理对象
   
   2.java.lang.reflect.invocationHander接口:
   public invoke(Object proxy, Method method,Object[] args)
   
   方法职责:负责集中处理动态代理类上的所有方法调用
   参数:
   proxy:生成代理对象
   methos:当前调用的真实方法对象
   args:当前调用方法的实参
   返回:真实方法的返回结果n

二.JDK 动态代理操作步骤:

1.创建一个代理对象
2.实现invocationHander接口
3.覆盖invoke(),为真实对象方法做增强的具体操作        

代码演示:

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;//真实对象,即对谁做增强
    private TransactionManager txManager;//事务管理器(模拟)
    
    public void setTarger(Object targer) {
        this.targer = targer;
    }
    public void setTxManager(TransactionManager txManager) {
        this.txManager = txManager;
    }
    
    //创建一个代理对象
    public <T> T getproxyObject() {
        return (T) Proxy.newProxyInstance(targer.getClass().getClassLoader(),//loader类加载器,一般跟上真实对象的类加载器
                
                targer.getClass().getInterfaces(),//真实对象所实现的接口(jdk动态代理必须要求真实对象有接口)
                
                this);//如何做事务增强的对象因为继承了InvocationHandler,所以直接用this就可以了
    }
    @Override
    //如何为真实对象的方法增强的具体操作
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object ret = null;
        txManager.begin();
        //调用真实对象的方法
          try {
            ret = method.invoke(targer, args);//调用对象真实的方法
            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"/>

<!-- 事务管理器 -->
<bean id = "transactionManager" class = "com.keen.proxy.tx.TransactionManager"/>

<!-- 配置事务增强类 -->

<bean id = "transactionManagerAdvice" class = "com.keen.proxy.tx.TransactionManagerAdvice" >
  <property name="txManager" ref ="transactionManager"/>
  <property name="targer" >
    <!-- 把employeeService作为内部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());
        
    }
    
}

⚠️:其他涉及相关的类和上一篇静态代理的类一样的,只是动态代理不需要静态代理那个IEmployeeServiceProxy类了。我们用TransactionManagerAdvice 替代了。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,598评论 18 139
  • Spring Web MVC Spring Web MVC 是包含在 Spring 框架中的 Web 框架,建立于...
    Hsinwong阅读 22,310评论 1 92
  • 2016年12月30号,本年度最后一天个工作日,到处都是放假的气氛,不能专心做事。 重新安装了简书客户端,才意识到...
    忘念阅读 210评论 0 0
  • 大年初一看了电影《红海行动》,半个月前老公就嚷着说要陪他一起去看的电影,终于一睹为快了。 影片讲述的是伊维亚共和国...
    慧慧2018阅读 500评论 1 1