Spring JDK动态代理

JDK动态代理和原理

jdk的动态代理:必须有接口

字节码加载:

                            

                本|------byte[]字节码流-------->类加载器

                地|                             |                  

                和|                            JVM  

   Java文件      网|                  V

     |         络|                    Java解释器   即使编译器  

      V         上|

   编译器        的|                           运行系统

      |         字| 

      |         节|                           操作系统

      V         码|     

   字节码文件-------|                            硬件

     

    编译时期                                   动态代理

    

 动态代理:省略编译时期,其他的部分就是动态代理(二进制流加载到JVM),不需要编译文件。

 

 在静态代理  每一个需要代理的类都要创建一个代理类,而动态代理中可以避免创建多个动态代理类。

 

 

 

JDK的动态代理:

public class TranscationMangeAdvice {

//真实对象

private Object target;

//创建一个代理类对象

public Object getProxyObject() {

 

/*Proxy.newProxyInstance(loader, interfaces, h);

* 第一个参数:

*loader:类加载器,真实对象的类加载器--对谁做增强

*第二个参数:

*interfaces:真实对象所实现的接口--数组的形式,new Class[]{IEmployeeService.class.....}可以这样写  单个或者多个,但是这样就写死了。

*target.getClass().getInterfaces() 返回值整好是一个数组

*第三个参数:

*h:这个参数表示 如何做事物增强的对象,如下面new xx();对象

*Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new xx());

*/

//第3个参数h 的实现方式1:

public Object getProxyObject() {

return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new xx());//返回一个object类型的代理对象,需要强转

}

}

 

  //第一种:最后一个参数的表示方式-->使用一个类实现InvocationHandler接口并覆盖里面的方法

  class xx implements InvocationHandler{

 

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

return null;

}

}

}

 

 

//第3个参数h 的实现方式2:最后一个参数的表示方式-->使用本类实现InvocationHandler接口并覆盖里面的方法,并传入当前对象this

public class TranscationMangeAdvice implements InvocationHandler{

//真实对象

private Object target;

//创建一个代理类对象

public Object getProxyObject() {

return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);//返回一个object类型的代理对象,需要强转

}

 

//第二种实现第三个参数的方式:

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

return null;

}

}

 

//解决返回值为Object的问题:

  

 public class TranscationMangeAdvice implements InvocationHandler{

//真实对象

private Object target;

//创建一个代理类对象

public <T> T  getProxyObject() {

return (T)Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);//返回一个object类型的代理对象,需要强转

}

 

//第二种实现第三个参数的方式:

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

return null;

}

}

 

 编辑xml配置文件

 <!-- DI注解解析器 -->

<context:annotation-config/>

 

<!-- Dao的实现对象 -->

<bean id="employeeDao" class="Spring_StaticPoxy_Data.EmployeeIMPL"/>

 

<!-- data-domain -->

<bean id="employDmain" class="Spring_StaticPoxy_Data.EmployeeDomain">

<property name="id" value="100"/>

<property name="name" value="wangqiang"/>

<property name="deptnum" value="022"/>

</bean>

 

<!-- service  真实对象 -->

<bean id="EmployeeService" class="Spring_StaticPoxy_Service.EmployeeServiceIMPL">

<property name="employee" ref="employeeDao"/>

</bean>

 

<!-- 处理事务 -->

<bean id="transcations" class="Transcations.Source_Transcation"/>

 

<!-- 配置事物增强的类 -->

<bean id="MangeAdvice" class="Transcations.TranscationMangeAdvice">

<property name="target" ref="EmployeeService"/>

</bean>

 

操作测试类

@Autowired//数据对象

public  EmployeeDomain  employDmain;

@Autowired//获取事物增强对象

public TranscationMangeAdvice MangeAdvice;

 

@Test

public void testMangeAdviceInsert() {

//获取代理对象

IEmployeeService service=MangeAdvice.getProxyObject();

System.out.println("--------service---------"+service.getClass());//class com.sun.proxy.$Proxy20  

service.insert(employDmain);//但是调用之前的方法  没有反应,就是因为  我们还没有操作 第三个参数的增强方法

//你可以测试一下  在增强方法输出一句话  看一下控制台是否有输出。

}

 

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

/*

Object proxy:代理对象

Method method:当前被增强的方法

Object[] args:当前被增强的方法的参数

*/

System.out.println("------代理对象-----------"+proxy.getClass());

System.out.println("------当前被增强的方法-----------"+method);

System.out.println("------当前被增强的方法的参数-----------"+Arrays.toString(args));

return 12345;

}

 

 打印的结果为:

--代理对象-----------class com.sun.proxy.$Proxy20

//当前的方法为insert()方法:

--当前被增强的方法-----public abstract void Spring_StaticPoxy_Service.IEmployeeService.insert(Spring_StaticPoxy_Data.EmployeeDomain)

//当前方法传入的参数为:EmployeeDomain

--当前被增强的方法的参数-----[EmployeeDomain(id=100, name=wangqiang, deptnum=22)]

<!-- data-domain -->

<bean id="employDmain" class="Spring_StaticPoxy_Data.EmployeeDomain">

<property name="id" value="100"/>

<property name="name" value="wangqiang"/>

<property name="deptnum" value="022"/>

</bean>

 

//通过反射调用方法--target.insert(args),如果有返回可以进行接收一下

Object  ret=method.invoke(target, args);//这时是没有做任何的增强操作

//如果做增强操作可以在  这个方法体内进行具体的操作

------------增强的方法-----------------------

Object  ret=method.invoke(target, args);

    ------------增强的方法-------------------------

 

--------开启事物---------

--------回滚事物---------

--------关闭事物---------

JDK 动态代理的原理:

首先考虑的是  现在的业务逻辑只是针对Employee这个类有效呢  还是对所有的类的业务逻辑有效

源码百度云盘自取:链接:https://pan.baidu.com/s/17h6jq8OkHlLTrMpruHho2w  密码:q0xx

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值