欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

jdk动态代理的实现流程(事务处理)

程序员文章站 2022-07-12 17:02:24
...
  • JDK动态代理的定义及功能
  • 动态代理就是使用JDK的反射机制创建对象的能力,创建的是代理类的对象,而不是类文件,不用写java文件。
  • 动态代理常用的有两类,jdk动态代理和cglib动态代理。将jdk动态代理必须有接口,且代理类对象必须实现接口。没有接口时使用cglib动态代理。
  • 主要的功能就是功能增强,在后面代码中我会加以说明。另外一种功能就是控制访问。
  • 动态代理的核心方法及思路理解
  • java.lang.reflect:反射包,里面有三个类,InvocationHandler , Method, Proxy。
  • 实现InvocationHandler接口,接口中有一个方法invoke(),它表示代理对象要执行的功能代码。
  • Method类:过Method可以执行某个目标类的方法,Method.invoke(),相当于静态代理中你要执行的方法的调用。
  • Proxy类:核心的对象,创建代理对象。我们通常设置对象都是使用new类的构造方法的方式,在动态代理中,我们使用Proxy类来代替new使用。
  • 它有三个参数:(1)ClassLoader loader:类加载器,负责向内存中加载对象。(2)Class<?>[] interfaces:获取目标对象的实现类接口。(3)InvocationHandler:代理类对象,表示代理类要完成的功能。
  • 代理类的代码实现与理解

实现代理类对象

我就用动态代理实现事务提交这个功能来举个栗子吧,推荐从测试类中开始开效果更好哦!

public class TransactionInvocationHandler implements InvocationHandler {

    private Object target;//用来指定要实现动态代理的实现类

    public  TransactionInvocationHandler(Object target){
        this.target = target;
    }

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

        SqlSession session = null;//获取SqlSession用来获取dao层的连接
        Object obj = null;//方法的返回值对象

        try{

            //获取dao层连接,关于这个不懂的同学可以去看看mybatis
            session = SqlSessionUtil.getSession();

            //处理业务逻辑,相当于静态代理中的方法执行。在它的前后部分可以编写其他方法,只要使用动态代理对象调用方法,就会执行你在invoke方法前后定义的方法
            obj = method.invoke(target, args);

            //处理业务逻辑完毕后,提交事务
            session.commit();

        }catch(Exception e){

            session.rollback();

            e.printStackTrace();
        }finally {
            //使用工具类关闭连接
            SqlSessionUtil.myClose(session);
        }

        return obj;
    }

    public Object getProxy(){

        //参数传入TransactionInvocationHandler这个类对象,用于获取target为目标类的动态代理对象
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);

    }
}

获取service层的动态代理对象的工具类,通过传入的service实现类获取该类动态代理对象

//参数service为service层实现某种方法的实现类对象
public class ServiceFactory {

	public static Object getService(Object service){

    return new TransactionInvocationHandler(service).getProxy();

	}
}

使用动态代理进行测试

public class MyApp {
    
    @Test
    public void test01() {

        //通过new的方式创建静态的service对象
        StudentService service = new StudentServiceImpl();

        //添加一条数据试试
        Student student = new Student();
        student.setId("1314225");
        student.setName("xihai");
        student.setAge(20);
        
        //由于sqlsession默认是不自动提交的,所以数据库中并没有插入数据,
        //具体的dao实现方法insert就自己写吧,我主要不是讲数据库方面内容,只是为了更好的理解才举例说明事务的处理
        service.insert(student);
    }
    
    @Test
    public void test02() {

        //使用jdk的Proxy创建动态代理对象
        StudentService serviceProxy = (StudentService) ServiceFactory.getService(new StudentServiceImpl());

        //测试添加操作
        Student student = new Student();
        student.setId("1314226");
        student.setName("shengge");
        student.setAge(21);
        //插入成功,由于动态代理对象中添加了事务提交功能。
        /*
        这里会去执行TransactionInvocationHandler对象中的invoke方法。
        对象的invoke方法的三个参数分别代表着serviceProxy代理对象,insert方法,student参数。
        */
        serviceProxy.insert(student);
    }
}