您的位置:首页 > 编程语言 > Java开发

Spring学习心得(13)-- jdk动态代理

2017-03-14 15:07 405 查看


引入:

在前面我们涉及到了静态代理,并且了解了它的缺点之后,我们来谈一下动态代理。


首先动态代理分成以下几种情况:

1、目标类和代理类实现共同的接口 

a)、jdk代理(即借助了jdk的API完成) 

2、代理类继承了目标类 

a)、hibernate:javasist 

b)、spring:cglib 

注:javasist是一个jar包,在学习hibernate的时候,我们使用了
Person person=session.load(Class clazz,Serializable id);
 

其中session.load得到的是一个javasist类,这一点在以前hibernate的帖子大家可以看到,这个就是javasist类,继承了Person类,所以它不用强转类型 。同时cglib也是一个包,这个在后面我们会讨论到。



我们就拿jdk动态代理来重构一下以前的hibernate例子

//首先,我们需要创建一个核心类:student
public class Student implements Serializable {
private Long sid;
private String sname;
private String sdescription;
//省略getter&setter
}

//接口:
public interface StudentDAO {
//增加学生
public void saveStudent(Student student);
//修改学生
public void updateStudent(Student student,Serializable id);
//删除学生
public void deleteStudent(Student student);
}

//事务类
public class MyTransaction extends hibernateUtils{
private Transaction myTransaction;
//开启事务
public void beginTransaction(){
myTransaction=sessionFactory.getCurrentSession().beginTransaction();
}
//提交事务
public void commit(){
myTransaction.commit();
}
}
//帮助类
public class hibernateUtils {
static SessionFactory sessionFactory;
static{
Configuration configuration=new Configuration();
//按照指定位置及名字读物hibernate的配置文件
configuration.configure("cn/ansel/hibernate/jdkProxy/hibernate.cfg.xml");
//得到sessionFactory
sessionFactory=configuration.buildSessionFactory();
}
}

//目标类
public class StudentDAOImpl extends hibernateUtils implements StudentDAO {
//因为下面都要用到session,免去重复些代码
private Session session=sessionFactory.getCurrentSession();

//删除学生
@Override
public void deleteStudent(Student student) {
session.delete(student);
}

//保存学生
@Override
public void saveStudent(Student student) {
session.save(student);
}

//修改学生
@Override
public void updateStudent(Student student, Serializable id) {
session.get(student.getClass(), id);
session.update(student);
}
}

//拦截器:
public class StudentInterceptor implements InvocationHandler {
/**
* 拦截器的定义:
* 1、引入目标类
* 2、引入事务
* 3、利用构造函数把目标类和事务导入
* 4、填充invoke方法,
*/
private Object target;
private MyTransaction myTransaction;

public StudentInterceptor(Object target, MyTransaction myTransaction) {
this.target = target;
this.myTransaction = myTransaction;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//在这里考虑到事务,但是在目标类中不考虑事务
myTransaction.beginTransaction();
method.invoke(target, args);
myTransaction.commit();
return null;
}
}

//映射文件:Student.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<!--
把相应的核心类导入
-->
<class name="cn.ansel.hibernate.jdkProxy.Student">
<!--
给其中的属性赋值
-->
<id name="sid" length="11">
<generator class="increment"></generator>
</id>
<property name="sname" length="11"></property>
<property name="sdescription" length="111"></property>
</class>
</hibernate-mapping>
配置文件:hibernate.cfg.xml 



需要特别注意的就是我们使用了session.getCurrentSession,所以要在配置文件中添加图中红色部分的属性。

//然后是测试类:
public class jdkProxyTest {
@Test
public void test(){
//获取事务
MyTransaction myTransaction=new MyTransaction();
//得到目标类
Object target=new StudentDAOImpl();
//得到拦截器类,并把事务跟目标类传入
StudentInterceptor interceptor=new StudentInterceptor(target, myTransaction);
//**调用代理类的方法,得到代理对象**,
//这里需要的三个参数:
//第一个是目标类的加载器,
//第二个是目标类实现的接口
//第三个是拦截器
StudentDAO dao=(StudentDAO) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), interceptor);
//新建学生
Student student=new Student();
//使用动态代理对象添加学生
dao.saveStudent(student);
}
}

运行结果: 



1、 代理对象有多少方法,方法的名称是什么?

因为代理对象和目标类一样,同样的实现了接口,所以接口中有多少方法,代理对象中就有多少个方法,名称和接口中的方法的名称一样。

2、 拦截器中的invoke方法在什么时候执行的?

当在客户端,代理对象调用方法的时候,进入到了invoke方法

3、 拦截器中的invoke方法中的method参数在什么时候传递的值?

当在客户端,代理对象调用方法的时候,进入到了invoke方法,这个时候,method参数就是代理对象调用的方法。

4、 代理对象的方法体的内容是什么?

代理对象的方法体的内容就是invoke方法体的内容

代理对象的方法体:

1、 开启事务

2、 目标方法

3、 事务的提交

4、 代理对象的方法体就把事务和目标方法结合在一起了,这样做的目的就是为了让目标类的目标方法和事务的方法松耦合。

流程图

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: