JDK动态代理
来源:互联网 发布:死是什么感觉 知乎 编辑:程序博客网 时间:2024/06/05 08:16
1、背景
Spring AOP使用动态代理技术在运行期织入增强的代码,Spring AOP 的底层使用了两种代理模式一种是JDK的动态代理,另一种是基于CGLIB的动态代理。之所以需要两种代理机制,很大程度上是因为JDK本身只提供接口的代理,而不支持类的代理。2、JDKProxy的代码
package com.itheima.spring.jdkproxy;
public interface PersonDao {
public void savePerson();
}
package com.itheima.spring.jdkproxy;
public class PersonDaoImpl implements PersonDao{
@Override
public void savePerson() {
System.out.println("save person");
}
}
package com.itheima.spring.jdkproxy;
public class Transaction {
public void beginTransaction(){
System.out.println("begin transcation");
}
public void commit() {
System.out.println("commit");
}
}
package com.itheima.spring.jdkproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* 拦截器:
* 1、目标类导入进来
* 2、事务导入进来
* 3、invoke完成
* ①开启事务
* ②调用目标对象的方法
* ③事务提交
* @author xx
*
*/
public class MyInterceptor implements InvocationHandler{
private Object target;//目标类
private Transaction transaction;//事务,在这里代表一种功能,但如果要插入多个功能,就不能这么写了,看下一个案例,可以把他们加入在一个拦截器链表里
public MyInterceptor(Object target, Transaction transaction) {
super();
this.target = target;
this.transaction = transaction;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
String methodName = method.getName();
if("savePerson".equals(methodName) || "updatePerson".equals(methodName)
|| "deletePerson".equals(methodName)){
this.transaction.beginTransaction();//开启 事务
method.invoke(target);//调用目标方法
this.transaction.commit();//事务的提交
}else{
method.invoke(target);
}
return null;
}
}
package com.itheima.spring.jdkproxy;
import java.lang.reflect.Proxy;
import org.junit.Test;
/**
* 1、拦截器的invoke方法是在是什么时候执行的?
* 当在客户端,代理对象调用方法的时候,进入到了拦截器的invoke方法
* 2、代理对象的方法体的内容是什么?
* 拦截器的invoke方法的内容就是代理对象的方法的内容
* 3、拦截器中的invoke方法的参数method是谁在什么时候传递过来的?
* 代理对象调用方法的时候,进入了拦截器中的invoke方法,所以invoke
* 方法中的参数method就是代理对象调用的方法
* @author xx
*/
public class JDKProxyTest {
/**
* 1、创建一个目标类
* 2、创建一个事务
* 3、创建一个拦截器
* 4、动态生成一个代理对象
*/
@Test
public void test() {
Object target = new PersonDaoImpl();
Transaction transaction = new Transaction();
MyInterceptor interceptor = new MyInterceptor(target,transaction);
/*
*1、目标类的加载器
*2、目标类的所有的接口
*3、拦截器
*/
PersonDao personDao = (PersonDao) Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), interceptor);
personDao.savePerson();
}
}
思考
动态代理是怎么生成的?
jdk动态代理比静态代理先进(不同)在哪?有什么优势?
以上的JdkProxy代码有什么缺点?
3、另一种改进的JDK动态代理模式
package com.itheima.spring.jdkproxy;
/**
* 给日志、事务等做了一个抽象,而这个抽象就是Interceptor
* @author xx
*
*/
public interface Interceptor {
/*
* 除了目标对象的目标方法之外,其他任何的功能,比如事务、日志等都写在interceptor里面
*/
public void interceptor();
}
package com.itheima.spring.jdkproxy;
/**
* Spring的实现比这复杂,用的责任链模式
* @author xx
*
*/
public class Transaction implements Interceptor{
@Override
public void interceptor() {
System.out.println("transaction");
}
}
package com.itheima.spring.jdkproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.List;
/**
* 拦截器:
* 1、目标类导入进来
* 2、事务导入进来
* 3、invoke完成
* ①开启事务
* ②调用目标对象的方法
* ③事务提交
* @author xx
*
*/
public class MyInterceptor implements InvocationHandler{
private Object target;//目标类
List<Interceptor> interceptors;
public MyInterceptor(Object target, List<Interceptor> interceptors) {
super();
this.target = target;
this.interceptors = interceptors;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
String methodName = method.getName();
if("savePerson".equals(methodName) || "updatePerson".equals(methodName)
|| "deletePerson".equals(methodName)){
for(Interceptor interceptor: interceptors){
interceptor.interceptor();
}
}
method.invoke(target);
return null;
}
}
package com.itheima.spring.jdkproxy;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
/**
* 1、拦截器的invoke方法是在是什么时候执行的?
* 当在客户端,代理对象调用方法的时候,进入到了拦截器的invoke方法
* 2、代理对象的方法体的内容是什么?
* 拦截器的invoke方法的内容就是代理对象的方法的内容
* 3、拦截器中的invoke方法的参数method是谁在什么时候传递过来的?
* 代理对象调用方法的时候,进入了拦截器中的invoke方法,所以invoke
* 方法中的参数method就是代理对象调用的方法
* @author xx
*/
public class JDKProxyTest {
/**
* 1、创建一个目标类
* 2、创建一个事务
* 3、创建一个拦截器
* 4、动态生成一个代理对象
*/
@Test
public void test() {
Object target = new PersonDaoImpl();
Transaction transaction = new Transaction();
List<Interceptor> interceptors = new ArrayList<Interceptor>();
interceptors.add(transaction);
MyInterceptor interceptor = new MyInterceptor(target,interceptors);
/*
*1、目标类的加载器
*2、目标类的所有的接口
*3、拦截器
*/
PersonDao personDao = (PersonDao) Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), interceptor);
personDao.savePerson();
}
}
思考
改进的代码解决了什么问题?
0 0
- 代理模式,JDK动态代理
- Java动态代理--jdk代理
- 代理模式-JDK动态代理
- JDK中的动态代理
- JDK动态代理
- JDK动态代理
- JDK动态代理
- jdk动态代理(暂)
- JDK动态代理
- JDK动态代理实例
- jdk 动态代理
- JDK动态代理
- JDK动态代理说明
- jdk动态代理
- JDKDynamicProxy JDK动态代理
- JDK动态代理实现
- JDK 动态代理
- JDK动态代理
- 如何让孩子爱上设计模式 ——10.桥接模式(Bridge Pattern)
- Android手机病毒分析(二)
- AOP
- 贝叶斯推断及其互联网应用(三):拼写检查
- 学习图谱
- JDK动态代理
- BitMap的getRowBytes和getByteCount()
- Shaders for Game Programmers and Artists(7) - Non-photorealistic rendering
- [07]项目实战-PC 端固定布局(7)
- CGLib动态代理
- Synchronized(对象锁)和Static Synchronized(类锁)的区别
- 1720 (错误)
- codeforce 698B Fix a Tree
- TCP建立连接为什么是三次握手,为什么不是两次或四次?