美文网首页
Spring5-(10)JDK动态代理

Spring5-(10)JDK动态代理

作者: 小白201808 | 来源:发表于2018-09-26 09:37 被阅读24次

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

   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 替代了。

相关文章

网友评论

      本文标题:Spring5-(10)JDK动态代理

      本文链接:https://www.haomeiwen.com/subject/hmfdoftx.html