内省(IntroSpector) 对javaBean操作
如果在两个模块之间传递多个信息,可以将这些信息封装到一个javaBean中,这种javaBean的实例对象通常称为
值对象(Value Objeect);
如果属性的第二个字母为小写,那么第一个字母就是小写
getCPU -- CPU
getTime-- time
gettime-- time
对javaBean的简单内省操作
PropertiesDescriptor属性描述类
getReadMethod();//get
getWriteMethod();//set
Extract 抽取
复杂的内省操作:
BeanInfo = IntroSpector.getBeanInfo();
在getPropertyDescriptors();
通过getName 在equals属性名
package day2;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
//简单的内省操作javaBean 和复杂的内省操作javaBean
public class EasyIntroSpector
{
public static void main(String[] args)throws Exception
{
Person person=new Person("其实我很在乎你",10);
String propertyName="name";
String setValue="累了醉了就想哭";
//设置
setProperty(person, propertyName, setValue);
//获取
getProperty(person, propertyName);
}
private static void setProperty(Person person, String propertyName, String setValue)
throws IntrospectionException, IllegalAccessException, InvocationTargetException
{
//简单的内省操作
/*
PropertyDescriptor pDescriptor=new PropertyDescriptor(propertyName, person.getClass());
Method method=pDescriptor.getWriteMethod();
method.invoke(person, setValue);
*/
//复杂的内省操作
BeanInfo beanInfo= Introspector.getBeanInfo(person.getClass());
PropertyDescriptor[] pDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : pDescriptors)
{
if(propertyDescriptor.getName().equals(propertyName))
{
Method method=propertyDescriptor.getWriteMethod();
method.invoke(person, setValue);
}
}
}
private static void getProperty(Person person, String propertyName)
throws IntrospectionException, IllegalAccessException, InvocationTargetException
{
//简单的内省操作
/*PropertyDescriptor pdDescriptor=new PropertyDescriptor(propertyName, person.getClass());
Method method=pdDescriptor.getReadMethod();
System.out.println(method.invoke(person));*/
//复杂的内省操作
BeanInfo beanInfo=Introspector.getBeanInfo(person.getClass());
PropertyDescriptor[] propertyDescriptors=beanInfo.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : propertyDescriptors)
{
if(propertyDescriptor.getName().equals(propertyName))
{
Method method=propertyDescriptor.getReadMethod();
System.out.println(method.invoke(person));
}
}
}
}
使用BeanUtils工具类操作Bean
getProperty();
setProperty();
例如Date 符合属性 属性可以级联
PropertiesUtils操作Bean
BeanUtils与PropertiesUtils区别
1.BeanUtils可以使用字符串内部会自动转换,而PropertiesUtils只能使用本身的属性类型
package day2;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
//使用BeanUtils工具包操作 javaBean
public class BeanUtilsTest
{
public static void main(String[] args)throws Exception
{
//BeanUtils与PropertyUtils的区别
//前者可以传入字符串,内部会自动转换, 后者只能传自身属性的类型,因为内部不会有转换
Person person=new Person("关不上的窗",15);
String propertyName="name";
String setValue="我的故乡黑龙江";
BeanUtils.setProperty(person, propertyName, setValue);
String name=BeanUtils.getProperty(person, propertyName);
System.out.println(name);
String proString="age";
//不能传入字符串 内部不会自动转换 自己传自身的类型
//PropertyUtils.setProperty(person, proString, "15");
PropertyUtils.setProperty(person, proString, 60);
int age = (int)PropertyUtils.getProperty(person,proString);
System.out.println(age);
//Date级联 属性
System.out.println(BeanUtils.getProperty(person, "date.time"));
}
}
几个基本注解(Annotation)
1.@SuppressWarnings(); //传入的是数组,当只有一个值可以直接传入 {"unused","unchecked","deprecation","rawtypes"}
2.@Deprecated //过时的
@Override //重写
一个注解就是一个类
注解相当与一种标记,加了注解就等于打上了某种标记,没加就等于没有这种标记,以后javac编译器,开发工具和其他程序
就可以用反射来了解你的类及各种元素上有无何何种标记,告诉你有什么标记,就去干相应的事
标记可以加在包中,构造方法,普通方法,类,局部变量,成员变量上..
package day2;
//注解的入门
public class AnnotationTest
{
@SuppressWarnings("deprecation")//压缩警告,过时方法不警告
public static void main(String[] args)
{
show();
System.runFinalizersOnExit(false);
}
@Deprecated //标志为已过时方法
public static void show()
{
System.out.println("show方法");
}
@Override //加上注解如果复写方法不对 会编译错误
public String toString()
{
return AnnotationTest.class.getName();
}
}
注解类的应用结构
1.注解类 @interface
2.应用了注解的类
3.对应用了注解的类进行反射操作
isAnnotationPresent(注解类.class);
@Retent(RetentionPolicy.RUNTIME) 保留运行期间
RetentionPolicy.SOURCE 保留在源文件上
RetentionPolicy.CLASS 保留在class字节码文件上
@Target({ElementType.METHOD}) 注解可以存放位置例如方法METHOD,类TYPE
ElementType.METHOD
ElementType.FIELD
ElementType.LOCAL_VARIABLE
ElementType.TYPE
ElementType.PARAMTER
ElementType.CONSTRUCTOR
ElementType.PACKAGE
ElementType.ANNOTATION_TYPE
为注解类添加基本属性
String
int[]
只有一个设置值时,可以直接传入
可以设置默认值 加上default关键字即可
为注解添加高级属性, 枚举,注解类,Class等
package day2;
//注解的入门
public class AnnotationTest
{
@SuppressWarnings("deprecation")//压缩警告,过时方法不警告
public static void main(String[] args)
{
show();
System.runFinalizersOnExit(false);
}
@Deprecated //标志为已过时方法
public static void show()
{
System.out.println("show方法");
}
@Override //加上注解如果复写方法不对 会编译错误
public String toString()
{
return AnnotationTest.class.getName();
}
}
package day2;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Itcast
{
int value(); //当方法名为Value 只有一个参数可以 直接注解类(值)
}
package day2;
import java.lang.reflect.Method;
import java.nio.file.AccessMode;
import java.util.Arrays;
import day1.EnumTest3.Lamp;
//注解的高级应用
@AnnotationClass(getName = "类上")
public class AnnatationTest1
{
@SuppressWarnings("rawtypes")
@AnnotationClass(getName="方法上")
public static void main(String[] args)throws Exception
{
if(AnnatationTest1.class.isAnnotationPresent(AnnotationClass.class))
{
//注解类
AnnotationClass aClass=AnnatationTest1.class.getAnnotation(AnnotationClass.class);
System.out.println(Arrays.toString(aClass.getArr()));
System.out.println(aClass.getClass().getName());
System.out.println(aClass.getClass().getSuperclass().getName());
Itcast itcast=aClass.getItcast();
System.out.println(itcast.getClass().getName());
System.out.println("value值是:"+itcast.value());
Lamp lamp=aClass.getLamp();
System.out.println(lamp);
System.out.println(lamp.nextLamp());
Class clazz=aClass.getClassName();
System.out.println(clazz.getName());
}
Method method = AnnatationTest1.class.getMethod("main", String[].class);
if(method.isAnnotationPresent(AnnotationClass.class))
{
AnnotationClass aClass=AnnatationTest1.class.getAnnotation(AnnotationClass.class);
System.out.println(aClass.getName());
}
}
}
泛型
好处: 安全,避免了强制转换的麻烦
一个ArrayList<Integer>用反射来添加String元素
package day2;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
//反射 一个ArrayList<Integer>参数化类型 可以添加String实际类型参数
public class ReflectGeneric
{
public static void main(String[] args)throws Exception
{
List<Integer> list=new ArrayList<Integer>();
list.add(1);
System.out.println(list);
//反射 获取add方法
Method addMethod=list.getClass().getMethod("add", Object.class);
addMethod.invoke(list, new String("星星点灯"));
System.out.println(list);
}
}
ArrayList<E> 代表泛型类型
ArrayList<E> E代表类型变量,类型参数
ArrayList<Integer> 称为参数化类型
ArrayList<Integer> Integer称为类型参数,或类型参数实例
ArrayList<Integer> 念ArrayList typeof Integer
ArrayList 代表原始类型
参数化类型可以引用一个原始类型
Collection col=new ArrayList<Integer>();
原始类型可以引用一个参数化类型
Collection<Integer> col=new ArrayList();
参数化类型不存在继承关系
<String> <object> //不行
<Object> <String> //不行
在创建数组实例时,数组元素不能使用参数化类型
Vector<Integer>[] vectors=new Vector<Integer>[10]; //这是不允许的
思考题:
Vector v=new Vector<Integer>();//参数类类型引用给原始类型 允许的
Vector<Object> v1= v; //原始类型类参数化类型 可以的
泛型通配符扩展应用
? 代表任意类型,不确定的类型
只能作为传参引用时,调用与添加有关的参数时不行,只能调用与参数类型无关的方法
上限符:
<? extends Number> 只能接收Number或者该子类
下限符:
<? super Integer> 只能接收Integer以及他的父类
限定符总是包括自己
package day2;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
//泛型通配符扩展应用
public class GenericTest
{
public static void main(String[] args)
{
//print(new int[]{1,2,3}); //编译错误, 基本类型不能当作为实际参数
print(new String[]{"a","b"}); //可以, 引用类型数组可以
ArrayList<Integer> aList=new ArrayList<Integer>();
aList.add(10);
aList.add(1);
//show(aList);
show1(aList);
//上限符
ArrayList<? extends Number> al1=new ArrayList<Integer>();
//下限符
ArrayList<? super Integer> al3=new ArrayList<Integer>();
//String 不是Integer的父类
//ArrayList<? super Integer> al2=new ArrayList<String>();
}
public static <T> void print(T [] arr)
{
System.out.println(arr.length);
}
// ?代表不确定的类型 任意类型
public static void show(Collection<?> c)
{
//当?作为引用是时, 不能调用与添加有关的方法,只能使用与参数类型无关的方法
System.out.println(c.toString());
//c.add(1); 不能使用
c.clear();
}
//T 代表确定的类型
public static <T> void show1(Collection<T> c)
{
//当?作为引用是时, 不能调用与添加有关的方法,只能使用与参数类型无关的方法
System.out.println(c.toString());
//c.add(1); 不能使用
Iterator<T> it=c.iterator();
while (it.hasNext())
{
T t=it.next();
System.out.println(t);
}
}
}
泛型的综合案例, HashMap添加元素
package day1;
import java.util.HashMap;
import java.util.Map;
//泛型实例 Map
public class EnhanceFor
{
public static void main(String[] args)
{
Map<String, String> map = new HashMap<String, String>();
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
for (Map.Entry<String, String> mEntry : map.entrySet())
{
System.out.println(mEntry.getKey()+"---"+mEntry.getValue());
}
自定义泛型方法
// x y 可以传入任意类型, 最大的交集就是Object
private static <T> T add (T x , T y)
{
//return x+y; 这是不允许的,因为类型的不确定是否能运算
return x;
}
java泛型完全是在编译器中实现的
T不能是基本类型,只能是引用类型,才能作为实际参数
<V extends Serializable&Cloneable> 必须实现这两接口的类型
普通类,构造方法,静态方法,都可以使用泛型
数组实例不能使用参数化类型
泛型参数可以有多个,例如Map<K,V>
泛型的类型推断还有传递性
泛型类
静态不能使用泛型类
package day2;
//泛型类
public class GenericClass<T>
{
@SuppressWarnings("unused")
private T t;
/*
//静态方法不能使用 类泛型
public static void show(T t)
{
}
*/
public static <T> void method(T t)
{
}
public void show(T t)
{
System.out.println(t);
}
}
通过反射获取泛型的实际参数类型
getGenericParamterTypes();
getParameterTypes();
ParameterizedType参数化类型类
getRawType();
getActualTypeArguments();
package day2;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
//反射获取参数泛型类型
public class GenericTest1
{
public static void main(String[] args)throws Exception
{
show(new String("尼玛"));
show(new Integer(1));
Method method=GenericTest1.class.getMethod("print", Collection.class);
Type[] types = method.getGenericParameterTypes();
ParameterizedType pType=(ParameterizedType)types[0];
System.out.println(pType.getRawType());
//System.out.println(pType.getActualTypeArguments()[0]);
Type[] types2=pType.getActualTypeArguments();
System.out.println(types2[0]);
}
//接收任意类型并打印
public static <T> void show(T t)
{
System.out.println(t);
}
public static void print(Collection<String> collection)
{
}
}
类加载器 加载类的工具
系统默认的三个主要加载器
1.BootStrap 查找rt.jar
2.ExtClassLoader 查找ext/下的jar包
3.AppClassLoader 查找classpath路径
类加载器也是java类,BootStrap不是,是c写的二进制文件
类.getClassLoader();获取当前类的类加载器
getParent(); //获取父类
因为BootStrap不是java类,所以返回null
java中所有的类加载都是采用父子关系的树状结构图进行组织
ClassLoader类
package day3;
//遍历 类加载器
public class ClassLoaderbase
{
public static void main(String[] args)
{
ClassLoader loader=ClassLoaderbase.class.getClassLoader();
System.out.println(loader);
while(loader!=null)
{
loader=loader.getParent();
System.out.println(loader);
}
//最*的父类BootStrap因为不是java类 所以返回null
}
}
类加载器的委托机制
首先会找对*的父类,如果没有就一级一级的往下查找,如果到了触发者这里还没有就抛ClassNotFoundException
自定义加密Class文件
自定义解密Class文件
package day3;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import com.sun.org.apache.bcel.internal.util.ByteSequence;
//加解密 自动加载器类
@SuppressWarnings("unused")
public class MyClassLoader extends ClassLoader
{
private String classDir;
public MyClassLoader(String classDir)
{
this.classDir=classDir;
}
public static void main(String[] args)throws Exception
{
String yuan=args[0];
String filename=yuan.substring(yuan.lastIndexOf(File.separator)+1);
String mudi=args[1]+File.separator+filename;
FileInputStream fis=new FileInputStream(yuan);
FileOutputStream fos=new FileOutputStream(mudi);
EncryptionAndDecryption(fis, fos);
}
public static void EncryptionAndDecryption(InputStream inStream,OutputStream outStream)
{
try
{
int b=0;
while((b=inStream.read())!=-1)
{
outStream.write(b ^ 0xff);
}
} catch (Exception e)
{
System.out.println("加解密文件失败");
}finally
{
try
{
if(inStream != null)
inStream.close();
} catch (Exception e2)
{
System.out.println("关流失败");
}
try
{
if(outStream != null)
outStream.close();
} catch (Exception e2)
{
System.out.println("关流失败");
}
}
}
//只需要复写findClass方法 就可以自动以类加载器了
@SuppressWarnings("deprecation")
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException
{
// TODO Auto-generated method stub
String filePath=classDir+File.separator+name+".class";
try
{
FileInputStream inStream=new FileInputStream(filePath);
ByteArrayOutputStream baos=new ByteArrayOutputStream();
EncryptionAndDecryption(inStream, baos);
inStream.close();
byte[]buf =baos.toByteArray();
return defineClass(buf, 0, buf.length);
} catch (Exception e)
{
// TODO: handle exception
}
return null;
}
}
package day3;
public class ClassLoaderTest
{
public static void main(String[] args)throws Exception
{
//使用已经加密的class文件new 运行出错
//System.out.println(new Test());
new MyClassLoader("E:\\android\\projects\\javaenhance1\\bin\\day3").loadClass("Test").newInstance();
}
}
loadClass();加载类
我们只需要复写findClass路径添加为自己的路径即可
defineClass(); 接收字节数组返回class
有包的类不能调用无包的类
一个类加载器的高级问题分析web
代理的概念与作用
Proxy代理
AOP (Aspect Oriented Program) 面向方面的编程
安全,事物,日志等功能要贯穿好多个模块中,他们就是交叉业务
AOP中,将交叉业务模块化,可以将切面代码异移动到原始方法的周围
动态代理技术
jvm自动生成类, 动态生成类,即动态代理类
package day3;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collection;
//动态代理类 演示
public class ProxyTest
{
public static void main(String[] args)
{
Class clazz = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
Constructor[] constructors=clazz.getConstructors();
for (Constructor constructor : constructors)
{
StringBuilder sbBuilder=new StringBuilder(constructor.getName());
Class[] classes=constructor.getParameterTypes();
sbBuilder.append('(');
for (Class class1 : classes)
{
sbBuilder.append(class1.getName());
}
if(classes!= null && classes.length!=0)
sbBuilder.deleteCharAt(sbBuilder.length()-1);
sbBuilder.append(')');
System.out.println(sbBuilder.toString());
}
Method[] methods=clazz.getMethods();
for (Method method : methods)
{
StringBuilder sbBuilder=new StringBuilder(method.getName());
Class[]classes=method.getParameterTypes();
sbBuilder.append('(');
for (Class classs : classes)
{
sbBuilder.append(classs.getCanonicalName());
}
sbBuilder.append(')');
System.out.println(sbBuilder.toString());
}
}
}
动态代理生成必须实现一个或多个接口
CGLIB可以生成没有接口的子类,代理类
Proxy.getProxyClass();
Proxy.newProxyInstance();
package day3;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collection;
//代理类实例化
public class ProxyTest1
{
public static void main(String[] args)throws Exception
{
//麻烦的实例化代理对象做法
Class clazz = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
Constructor constructor=clazz.getConstructor(InvocationHandler.class);
Collection collection=(Collection)constructor.newInstance(new InvocationHandler()
{
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
// TODO Auto-generated method stub
return null;
}
});
//返回为空
System.out.println(collection);
System.out.println(collection.toString());
//collection.add("add");//不能添加
System.out.println(collection.size()); //null 不能调用需要实例化对象的方法
//简单的一部到位做法
Collection collection1=(Collection)Proxy.newProxyInstance(
Collection.class.getClassLoader(),
new Class[]{Collection.class},
new InvocationHandler()
{
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
// TODO Auto-generated method stub
return null;
}
});
//返回为空
System.out.println(collection1);
System.out.println(collection1.toString());
//collection.add("add");//不能添加
System.out.println(collection1.size()); //null 不能调用需要实例化对象的
}
}
Client程序用Proxy的方法时,涉及三要素:代理对象 , 代理对象的方法, 方法参数
把目标返回结果返回到代理上
可以将代码封装对象,放在原方法的四个位置:
1.前
2.后
3.中间
4.catch处理代码块中
建议Advice接口
目标就是要生成代理类的类
package day3;
import java.lang.reflect.Method;
public interface Advice
{
void beforMethod(Method method);
void affterMethod(Method method);
}
package day3;
import java.lang.reflect.Method;
public class MyAdvice implements Advice
{
private long startTime;
private long endTime;
@Override
public void beforMethod(Method method)
{
startTime=System.currentTimeMillis();
System.out.println("事物,安全,日志 代码前 ");
System.out.println("方法名"+method.getName());
}
@Override
public void affterMethod(Method method)
{
endTime=System.currentTimeMillis();
System.out.println("执行所花费时间:"+(endTime-startTime));
System.out.println("事物,安全,日志 代码后 ");
}
}
package day3;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;
//代理类 封装成方法 对象
public class ProxyTest3
{
public static void main(String[] args)
{
final ArrayList target=new ArrayList();
final Advice advice=new MyAdvice();
Collection collection=(Collection)getProxy(target, advice);
collection.add("dd");
}
private static Object getProxy(final ArrayList target, final Advice advice)
{
Object object = Proxy.newProxyInstance(
target.getClass().getClassLoader()
, target.getClass().getInterfaces()
, new InvocationHandler()
{
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable
{
advice.beforMethod(method);
Object returnVal=method.invoke(target, args);
advice.affterMethod(method);
return returnVal;
}
});
return object;
}
}
实现类似Spring中的Aop框架
BeanFactory
getBean();
ProxyFactoryBean
getProxy();
package day3;
import java.io.InputStream;
public class AOPTest
{
public static void main(String[] args)
{
InputStream inStream=AOPTest.class.getResourceAsStream("lib/aop.properties");
Object object = new BeanFactory(inStream).getBean("className");
System.out.println(object);
}
}
package day3;
import java.io.InputStream;
import java.util.Properties;
public class BeanFactory
{
private Properties properties=new Properties();
public BeanFactory(InputStream inStream)
{
try
{
properties.load(inStream);
} catch (Exception e)
{
// TODO: handle exception
}
}
@SuppressWarnings("rawtypes")
public Object getBean(String name)
{
Object bean=null;
String className=properties.getProperty(name);
try
{
Class clazz=Class.forName(className);
bean=clazz.newInstance();
} catch (Exception e)
{
// TODO: handle exception
}
if(bean instanceof ProxyFactoryBean)
{
Object proxy=null;
ProxyFactoryBean pBean=(ProxyFactoryBean)bean;
try
{
Advice advice=(Advice)Class.forName(properties.getProperty(name+".advice")).newInstance();
Object target=Class.forName(properties.getProperty(name+".target")).newInstance();
pBean.setAdvice(advice);;
pBean.setTarget(target);
proxy = pBean.getProxy();
return proxy;
} catch (Exception e)
{
System.out.println("获取异常");
}
}
return bean;
}
}
package day3;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyFactoryBean
{
private Object target;
private Advice advice;
public Object getTarget()
{
return this.target;
}
public void setTarget(Object target)
{
this.target = target;
}
public Advice getAdvice()
{
return this.advice;
}
public void setAdvice(Advice advice)
{
this.advice = advice;
}
public Object getProxy()
{
final Object target=getTarget();
final Advice advice=getAdvice();
Object object = Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler()
{
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
advice.beforMethod(method);
Object returnValue=method.invoke(target, args);
advice.affterMethod(method);
return returnValue;
}
});
return object;
}
}
—————————— ASP.Net+Android+IOS开发、.Net培训、期待与您交流!——————————