最近学习了hibernate底层技术和spring 的底层技术,觉得很不错,所以想分享下,要是说的不够详细,可以去下载资源自己查看下载链接
技术的体现是在实际中的。现在大体介绍一下吧
首先介绍hibernate手动写:
仿HIBERNATE
hibernate是属于DAO,专门又来管理数据的,connection中还要考虑多线程的情况,同一个线程还要必须要是相同的connection对象,这就需要ThreadLocal来实
现。
1,connection考虑需要多线程,需要采用多例模式来实现,
2,读取配置文件,如真的hibernate中的配置文件(自己写的只有mysqld的)
3,当需要进行事物处理的时,需要采用同一个connection对象,需要用到ThreadLocal对象进行设置
4,当connection关闭时,而不是直接关闭,只是将其还回线程池中。
具体代码呈上:
<span style="font-size: 18px;"> /* * 我们需要采用线程池避免线程冲突,多例模式----》获得时候需要上锁 * pool中的数量是有限的,我们采用了代理模式,修改 con.close(),将连接换回来 * 为了保证统一线程是一个用户,我们采用threadlocal本地线程技术 */ public class hibernateFactory2 { private static final int NUM=3; private static List<Connection> pool =new ArrayList<Connection>(); </span><strong><span style="font-size:24px;color:#cc0000;"><u>private static ThreadLocal<Connection> t=new ThreadLocal<Connection>();//声明本地线程、</u></span></strong><span style="font-size: 18px;"> static{ </span><span style="color:#cc0000;font-size: 18px;"> <strong><u>//读取配置文件</u></strong> Properties p =new Properties(); </span><span style="font-size: 18px;"> try { p.load(hibernateFactory2.class.getClassLoader().getResourceAsStream("jdbc.properties")); //读取里面的值,一直修改配置文件即可 String driver=p.getProperty("driver"); String url=p.getProperty("url"); String user=p.getProperty("username"); String password=p.getProperty("password"); //System.out.println(driver+url+user+password); Class.forName(driver); for(int i=0;i<NUM;i++){ final Connection con=DriverManager.getConnection(url, user, password); </span><span style="color:#cc0000;font-size: 18px;"><strong><em><u>//采用动态代理开始进行对connection接口实现代理,对con.close,实现换回去</u></em></strong> Object o =Proxy.newProxyInstance(hibernateFactory2.class.getClassLoader(), new Class[]{Connection.class}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if(method.getName().equals("close")){ pool.add((Connection)(proxy)); System.out.println("换回来了。。。"); return null; } return method.invoke(con, args); } }); pool.add((Connection)o);</span><span style="font-size: 18px;"> } // System.out.println("初始化完毕"+con); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static synchronized Connection getCon() throws Exception{ /* * <span style="color:#ff0000;"><strong><em>把自动会到一个它所维护的那个map中去取,把以“当前线程对象”为key所对应的那个value取出来</em></strong></span> */ Connection c=t.get(); if(c==null){ while(pool.size()<=0){ System.out.println("池中已经乜有连接"); Thread.sleep(1000); } c=pool.remove(0);//为事物处理方便了,当出现错误的时候,多表一个都不能存储。采用一个connection t.set(c); } return c; } } </span>
仿Spring
这一层基本上进行的是业务逻辑处理
1,刚开始时候,将事务处理写在这一层,但是对于单个的函数的,每一个需要写,代码太繁琐了,所以直接将从servlet转到service的时候(切面技术),采用代理模式代理一下,在代理模式里面,我们采用进行事物处理,需要的我们拦截进行事物处理,不需要的,我们直接放行,做他自己的事情。
2,在使用代理模式的时候,为了让外面注入不需要强转,proxy里面采用了泛型的引入。
具体代码呈上:
public class Tx implements InvocationHandler{ private Object srcobj; private Object returnValue; public Tx(Object srcobj) { this.srcobj=srcobj; } <span style="color:#cc0000;"><strong>//这里写的是通用版本,代理模式</strong></span> //这个需要强转,所以引入了下面的那个不需要强转 // public static Object getProxy(Object srcobj){ // Object o =Proxy.newProxyInstance( // Tx.class.getClassLoader(), // srcobj.getClass().getInterfaces(), // new Tx(srcobj)); // return o; // } /* *<strong> 下面这个是升级版本,返回的类型不用强转</strong> */ public static<T> T getProxy(Object srcobj){ Object o =Proxy.newProxyInstance( Tx.class.getClassLoader(), srcobj.getClass().getInterfaces(), new Tx(srcobj)); return (T)o; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //所有的代理在这里开始 Connection con=null; <u><strong><span style="color:#ff0000;">if(method.isAnnotationPresent(MyTrans.class)){//这里采用注解的方式来区别是都需要进行事物处理</span></strong></u> System.out.println("被拦截了"); try { con =hibernateFactory2.getCon(); con.setAutoCommit(false); returnValue=method.invoke(srcobj, args);//调用被代理的自己去执行 con.commit(); System.out.println("事物提交成功"); } catch (Exception e) { try { System.out.println("回滚了"+e.getMessage()); con.rollback(); }catch (SQLException e1) { throw new RuntimeException("回滚失败"+e.getMessage()); } }finally{ try { con.setAutoCommit(true); con.close();//这里关闭,是还回池中,采用代理模式修改过 }catch (SQLException e) { throw new RuntimeException("关闭数据库连接失败11"+e.getMessage()); } } }else{ System.out.println("不拦截,放行!!"); return method.invoke(srcobj, args); } return returnValue; } }
这是自己写的注解类
package cn.hncu.publs.tx; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME)//作用于运行时,默认在编译器 @Target(value=ElementType.METHOD)//作用于方法 public @interface MyTrans { }
源代码已上传下载链接
欢迎各位大神指点
时间: 2024-10-28 11:47:45