8.利用动态代理模式重构hibernate

动态代理模式:

   1产生的代理对象和目标对象实现了共同的接口

       jdk动态代理

   2代理对象是目标对象的子类

       hibernate: Person person = session.load(Person.class,1L);  javassisit

       spring:cglib动态代理

 

jdk的动态代理:

   1、因为是用jdkAPI做到的

   2、代理对象是动态产生的

cglib产生的代理类是目标类的子类

 

注意事项:

    1、拦截器中invoke方法体的内容就是代理对象方法体的内容

    2、当客户端执行代理对象.方法时,进入到了拦截器的invoke方法体

    3、拦截器中invoke方法的method参数是在调用的时候赋值的


例子

存入数据库的person

public class Person implements Serializable{

private Long pid;

private String pname;

private String psex;

           set,get方法}

 

接口PersonDao

public interface PersonDao {

public String savePerson(Person person);}

 

hibernate工具类

public class HibernateUtils {

public static SessionFactory sessionFactory;

static{

Configuration config = new Configuration();

config.configure("/proxy/cn/itcast/jdkproxy/hibernate/hibernate.cfg.xml");

sessionFactory = config.buildSessionFactory();}}

 

实现类PersonDaoImpl

    public class PersonDaoImpl extends HibernateUtils implements PersonDao{

        public String savePerson(Person person) {

            sessionFactory.getCurrentSession().save(person);

        return "save a person";

    }

 

事务切面Transaction

public class MyTransaction extends HibernateUtils{

private Transaction tran;

public void beginTran(){

    this.tran = sessionFactory.getCurrentSession().beginTransaction();}

public void commit(){

    this.tran.commit();}}

 

hibernate映射文件

<?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>

<!-- 用来描述一个持久化类 name 类全名     table 表名,默认值和类名一样 catalog 数据库名称,一般不写    -->

<class name="proxy.cn.itcast.jdkproxy.hibernate.Person">

<!-- 标示属性  和数据库中的主键对应    name  属性的名称  column 列的名称  -->

<id name="pid" column="pid" length="200" type="java.lang.Long">

<!-- 主键的产生器   就该告诉hibernate容器用什么样的方式产生主键   -->

<generator class="increment"></generator></id>

<!-- 描述一般属性 -->

<property name="pname" column="pname" length="20" type="string"></property>

<property name="psex" column="psex" length="10" type="java.lang.String"></property>

</class> 

</hibernate-mapping>

 

拦截器

public class PersonDaoInterceptor implements InvocationHandler{

private Object obj;

private MyTransaction myTran;


         public PersonDaoInterceptor(Object obj,MyTransaction myTran){

this.obj = obj;

this.myTran = myTran;}

@Override

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

throws Throwable {

this.myTran.beginTran();

Object obj = method.invoke(this.obj, args);

this.myTran.commit();

return obj;}}

 

测试类

 

public class ProxyTest {

@Test

    public void test1(){

        Object obj = new PersonDaoImpl();

        MyTransaction myTran = new MyTransaction();

        PersonDaoInterceptor interceptor= new PersonDaoInterceptor(obj, myTran);

        PersonDao pdao = (PersonDao) Proxy.newProxyInstance(obj.getClass().getClassLoader(),                    obj.getClass().getInterfaces(), interceptor);

        Person person = new Person();

        person.setPname("pengya");

        person.setPsex("female");

        String s = pdao.savePerson(person);

        System.out.println(s); 

    }

}

 

8.cglib的动态代理

cglib产生的代理类是目标类的子类

 

1.拦截器实现net.sf.cglib.proxy.MethodInterceptor;

2.代码加强机制-生成代理对象

public Object createProxy(){

    Enhancer enhancer = new Enhancer();

    enhancer.setCallback((Callback) this);

    enhancer.setSuperclass(this.target.getClass());

    return enhancer.create();

}

3.覆盖intercept方法

@Override

public Object intercept(Object obj, Method method, Object[] obj2,

    MethodProxy methodproxy) throws Throwable {

    for(Interceptor interceptor : interceptors){

    interceptor.interceptor();

    }

    method.invoke(this.target, obj2);

    return null;

}

 

4.测试类

    SalaryInterceptor salaryinterceptor = new SalaryInterceptor(target, list);

    SalaryManager sm = (SalaryManagerImpl) salaryinterceptor.createProxy();

    sm.showSalary();