工大后院

 找回密码
 加入后院

扫一扫,访问微社区

QQ登录

只需一步,快速开始

搜索
楼主: powerwind

[已解决]Hibernate为什么可以访问private的setXXX()方法

[复制链接]
 楼主| 发表于 2006-9-14 19:52 | 显示全部楼层
今天看到有关ASM的资料和CGLIB的资料,应该是它们在作怪了.
ASM可以直接修改JAVA类文件的 bytecode,直接写入虚拟机指令,这还有什么做不什么来的呢?
而CGLIB大概是把ASM做得更"JAVA"些.
以后有机会再慢慢看看怎么回事.

ASM的介绍
asm的eclipse插件

[ 本帖最后由 powerwind 于 2006-9-14 19:56 编辑 ]
回复

使用道具 举报

发表于 2006-9-28 00:38 | 显示全部楼层
hibernate映射javabean,其实就是javabean的实例。
回复

使用道具 举报

 楼主| 发表于 2006-9-28 01:41 | 显示全部楼层
好像有资料介绍说,hibernate为持久化类创建代理子类.
应该不只是javabean的实例这么简单.
ASM和CGLIB是它实现的底层技术
回复

使用道具 举报

发表于 2006-10-11 21:07 | 显示全部楼层
反射机制确实有能力访问private级别的Field和Method,如:
//TestReflect.java 开始
import java.lang.reflect.*;

class Reflect{
        private int id;
       
        public Reflect(){
        }
       
        private void setId(int id){
                this.id=id;
        }
       
        public int getId(){
                return id;
        }
}

public class TestReflect{
        public static void main(String [] arg) throws Exception{
                Class class_tr=Class.forName("Reflect");
                Reflect tr=(Reflect)class_tr.newInstance();
                Field f_id=class_tr.getDeclaredField("id");
                f_id.setAccessible(true);
                f_id.setInt(tr,2);
                System.out.println("private filed 'id' :"+tr.getId());
        }
}
//结束

运行结果打印出:
private filed 'id' :2

如果反射机制不能访问private级别的Field或者Method,就失去了它了意义,因为"反射机制"是:"是指程序可以访问、检测和修改它本身状态或行为的一种能力".

然而Hibernate是如何做到的,是否是通过反射机制就只能看其源码了...
回复

使用道具 举报

 楼主| 发表于 2006-10-12 13:18 | 显示全部楼层
原来如此!
因为对反射机制不了解,一直以为不能访问private级别的Field或者Method。
感谢楼上的解答。
回复

使用道具 举报

发表于 2006-10-12 13:35 | 显示全部楼层
呵,总算解决了,恭喜!
回复

使用道具 举报

 楼主| 发表于 2006-10-12 16:50 | 显示全部楼层
在 <<J2ee development without ejb>>中文版 283页,有这样一句:

请注意,如果映射JavaBean属性,只跟Hibernate持久化相关的那些getter和setter可以是protected甚至private的,以保证由应用程序驱动字段的可见度.
页尾有这样的注释:


译者注:然而据译者的观察,如果将 setter声明为private,会导致 Hibernate 无法使用CGLIB优化的反射机制,只能通过标准的JAVA反射机制为持久对象

所有的持久化类(persistent classes)都要求有无参的构造器,因为Hibernate必须使用Java反射机制来为你创建对象。构造器(constructor)的访问级别可以是private,然而当生成运行时代理(runtime proxy)的时候则要求使用至少是package 级别的访问控制,这样在没有字节码指令(bytecode instrumentation)的情况下,从持久化类里获取数据会更有效率。
所有的持久化类(persistent classes)都要求有无参的构造器,因为Hibernate必须使用Java反射机制来为你创建对象。构造器(constructor)的访问级别可以是private,然而当生成运行时代理(runtime proxy)的时候则要求使用至少是package 级别的访问控制,这样在没有字节码指令(bytecode instrumentation)的情况下,从持久化类里获取数据会更有效率。


综合以前所有发现和楼主的解释,Hibernate应该是首选CGLIB,次选反射机制。

[ 本帖最后由 powerwind 于 2006-10-12 16:53 编辑 ]
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入后院

本版积分规则

QQ|Archiver|手机版|小黑屋|广告业务Q|工大后院 ( 粤ICP备10013660号 )

GMT+8, 2025-5-13 08:08

Powered by Discuz! X3.5

Copyright © 2001-2024 Tencent Cloud.

快速回复 返回顶部 返回列表