知识点一:内省JavaBean(特殊的Java类)
1.类中的方法以set或get打头的类。可以将JavaBean当作普通的类来操作,而不可以将普通类当作JavaBean操作。
一个类当作JavaBean使用时,可以根据方法的名字推断出Java的属性名。去掉get或set剩下的部分就是属性的名。
剩下部分的第二个字母是小写,则第一个字母就是要变成小写。剩下部分的第二个字母是大写则第一个字母则是大写。
如:getSun 属性名:sum
2.JavaBean包含的属性
boolean/Boolean :默认值为true int/Integer;默认值为100
String:默认值为字符串 double/Double:默认值为0.01D
例:
Class e1=Class.forName("Three11.javaBeanElement");//获取测试类的字节码
Objectbean=e1.newInstance();//通过字节码获取对象
BeanInfoinfo=Introspector.getBeanInfo(e1);//内省测试类,获取javaBean的属性信息
PropertyDescriptor[]pds=info.getPropertyDescriptors();//获取javaBean属性数组
//for迭代每个具体的属性
for(PropertyDescriptor pd : pds)
{
//获取属性名
Object name = pd.getName();
//获取属性类型
Object type =pd.getPropertyType();
//获取get方法
Method getMethod =pd.getReadMethod();
//获取set方法
Method setMethod =pd.getWriteMethod();
//因为测试类是一个本类所以要去除它
if(!"class".equals(name))
{
//调用修改前的属性
if(getMethod!=null)
System.out.println("修改前:"+getMethod.invoke(bean,null));
//修改各种属性
if(type==String.class)
setMethod.invoke(bean,"www.itcast.com");
else if(type==boolean.class)
setMethod.invoke(bean,true);
else if (type==double.class)
setMethod.invoke(bean,0.01d);
else if(type==int.class)
setMethod.invoke(bean,100);
//调用修改后的属性
if(getMethod!=null)
System.out.println("修改后:"+getMethod.invoke(bean,null));
}
}
知识点二:类加载器与类加载器的委托机制
(1)类加载器:
类加载器就是加载类的工具,Jvm运行的时候需要加载class文件,在内存中字节码。
加载class,并生成字节码文件的过程是由类加载器完成的。因为类加载器也是java类,
任何类都是需要类加载器加载的,所以一定有一个不是java类的加载器,BootStrap,
Jvm还内置了2个类加载器,ExtClassLoader和AppClassLoader,他们是由BootStrap加载。
BootStrap:加载的是 java包,javax包,这些系统级的包,在JRE/lib/rt.jar包内。
ExtClassLoader则JRE/lib/ext/*.jar,这里是加载该目录下的所有jar包。
如果要手动编写System类的话就必须自己编写一个类加载器,不要委托机制才可以加载到。
(2)类加载器的委托机制
类加载器加载线程中的第一个类,如果这个类中还有其他类的话,则用这个类加载器加载其他的类。就是A类中引用了B类,
那么加载AB类的加载器都是同一个。每个类加载器加载类的时候都会委托给上级加载,当上级没有加载到这个类的话就返回
给原加载器,如果还是加载不到就会报异常ClassnotFoundException。
例:
class Test12{
public static voidmain(String[]args)
{
for(String s:args)
{System.out.println(s);
}
}
}
//测试的类
class javaBeanElement
{
privateboolean flag;
privateint x;
private Stringstr;
privatechar[] ch;
privatelong l;
privatedouble d;
publicboolean isFlag() {
returnflag;
}
publicvoid setFlag(boolean flag) {
this.flag = flag;
}
publicint getX() {
returnx;
}
publicvoid setX(int x) {
this.x = x;
}
public String getStr() {
returnstr;
}
publicvoid setStr(String str) {
this.str = str;
}
publicdouble getD() {
returnd;
}
publicvoid setD(double d) {
this.d = d;
}
publicvoid show(long l)
{
this.l = l;
System.out.println("http://www.itcast.com");
}
}
知识点三:代理
(1)面向方面的编程AOP(Aspect Oriented Program)
系统中可能存在交叉业务需要切入到系统中的一方面,
如:
安全 事务 日志
StudentService ---|----------|------------|-------------
CourseService ----|----------|------------|-------------
MiscService ------|----------|------------|-------------
面向方面的编程的目标就是要是交叉的业务模块化,可以采用将切面代码移动到原始方法的周围,这与直接在方法中编写切面代码运行起来的效果是一样的,如:
------------------------------------------------------切面
func1 func2 func3
{ { {
.... .... ......
} } }
------------------------------------------------------切面
使用代理技术正好解决这样的问题,代理是实现AOP功能的核心和关键技术。
(2)Proxy类和InvocationHandler接口提供了生成动态代理的功能
例如:写一个ArrayList类的代理,实现和ArrayList中完全相同的功能,并可以计算每个方法运行的时间
publicclass Test1
{
public staticvoid main(String[] args)
{
//定义目标类
ArrayListtarget = new ArrayList();
//传递目标和系统功能到获取代理的函数//这里创建代理的时候必须是目标的父类
ListproxyList = (List)getProxy(target,new getSystemRunTime());
//使用返回的代理并计算使用了多少时间
proxyList.add(1);
proxyList.remove(0);
proxyList.size();
}
public staticObject getProxy(finalObject target,final getSystemRunTime time)
{
//建立代理
Object proxy = Proxy.newProxyInstance(
target.getClass().getClassLoader(),//定义代理类的类加载器
target.getClass().getInterfaces(),//代理类要实现的接口列表
new InvocationHandler() //调用处理程序
{
public Object invoke(Object proxy,Method method,Object[] args)throwsThrowable
{
//目标执行前代码
time.beforeCode();
//为了方便观看,设置了sleep
Thread.sleep(newRandom().nextInt(200));
//调用目标方法
Object obj = method.invoke(target, args);
//目标执行后代码
time.afterCode(method);
return obj;
}
});
//返回代理
return proxy;
}
}
//抽取出来的功能系统模版
abstract interface proxyAdvise
{
abstract void beforeCode();
abstract void afterCode(Method method);
}
//功能系统计算程序运行的时间
class getSystemRunTime implementsproxyAdvise
{
privatelong starttime;
publicvoid beforeCode()
{
//获取目标程序运行前的时间
starttime = System.currentTimeMillis();
}
publicvoid afterCode(Method method)
{
//获取目标程序运行后的时间并显示总共运行了多久
longendtime = System.currentTimeMillis();
System.out.println(method.getName()+"\t"+"method is ran "+"\t"+(endtime-starttime)+" ms");
}
}