美文网首页
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