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