反射和代理
反射
反射:refecton,反射机制:在运行过程中,可以动态获取到类中的任意的属性和方法(类型,方法,构造器,注解),可以动态的去操作对象的属性和方法,实现各种操作
编写:java源文件—》编译成:.class文件—》jvm加载到内存中—》解释执行—》操作系统
通过加载到内存中的class类型是实例,获取到该实例所代表的类中的(属性对象,方法对象,构造方法,对象)
Preson—》子类对象–》子类对象(参数)
反射是框架的基础
获取class类型的实例
1.Class.forName(“完全限定的类名”)使用频率高;耦合度低
2.类名.class
3.对象.getClass();
加载到内存中的Class类型的实例是唯一的,单例
public static void main(String[] args) {
try {
//获取Class类型的实例
final Class<?> aClass = Class.forName("com.aaa.lang.Student");
Class<Student> aClass1 = Student.class;
Student student=new Student();
Class<? extends Student> aClass2 = student.getClass();
//==:引用数据类型:比较地址 是否一样
System.out.println(aClass==aClass1);
System.out.println(aClass1==aClass2);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
获取类中的字段
Field类型
public static void main(String[] args) {
Student student=new Student();
try {
//获取Class类型的实例
Class<?> aClass = Class.forName("com.aaa.lang.Student");
//获取到公有的字段
Field[] fields = aClass.getFields();
// System.out.println(fields.length);
//获取类型中所有的字段
Field[] fields1 = aClass.getDeclaredFields();
// System.out.println(fields1.length);
//获取到该Class实例所代表的类的一个实例
Object object=aClass.newInstance();
//根据名字获取某字段
Field field = aClass.getDeclaredField("name");
//去掉安全限制,允许访问私有字段
field.setAccessible(true);
//参数1改字段所属的对象,参数2:给字段设置的值
field.set(student,"老胡");
//获取该对象中的该字段的值
System.out.println(field.get(student));
System.out.println(fields.length);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
获取类中的方法
Method类型
public static void main(String[] args) {
try {
Class<?> aClass = Class.forName("com.aaa.lang.Student");
//
//类型。。。参数名称:可变参数(变长参数),方法内部是一 数组的方式进行操作
Method say= aClass.getMethod("say", String.class);
//动态调用方法
//aClass.newInstance():对象
say.invoke(aClass.newInstance(),"老虎");
test1("hello",say);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
public static void test1(String str,Method method){
// method.invoke(,)
}
获取类中的构造方法
Constructor类型
public static void main(String[] args) {
try {
Class<?> aClass = Class.forName("com.aaa.lang.Student");
Constructor<?> constructor = aClass.getConstructor(String.class, Integer.class);
//创建对象
Object object = constructor.newInstance("sdf", 20);
Student student= (Student) object;
System.out.println(student.getName());
System.out.println(student.getAge());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
综合案例
Spring框架:IOC;Spring容器去创建对象
配置文件
init.propreties
stu1=com.aaa.lang.Student
empDao=com.aaa.lang.EmpDaoImpl
测试:
private static HashMap<String,Object> map=new HashMap<>();
//读取配置文件
public static void inti(){
//属性对象
Properties properties=new Properties();
//获取当前类class的实例:getClassLoader()获取对应的类加载器
InputStream stream = Spring.class.getResourceAsStream("init.properties");
try {
//加载数据流中的数据
properties.load(stream);
} catch (IOException e) {
e.printStackTrace();
}
//获取到文件中的键值对集合
Set<Map.Entry<Object, Object>> entries = properties.entrySet();
//遍历set集合:迭代器
Iterator<Map.Entry<Object,Object>> iterator=entries.iterator();
while (iterator.hasNext()){
//获取下一个元素:键值对的对象
Map.Entry<Object,Object> entry=iterator.next();
String key = entry.getKey().toString();
String value=entry.getValue().toString();
// System.out.println(key+":"+value);
try {
map.put(key, Class.forName(value).newInstance());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
//根据key获取对应的实例(对象)
Object object = map.get("empDao");
EmpDao dao= (EmpDao) object;
dao.show();
}
java语言局别一定的动态特性,灵活性增强,效率低
综合案例:模拟实现了Spring里面的IOC功能
提前创建爱你乙烯类对象,用的时候直接拿出来用
1.提前去创建对象
2.对象创建的容器(模拟spring容器)
实现步骤
1.准备一个HashMap集合,通过key获取value(Object)
2.需要把要创建的对象记录到文件中:xml
key1=完全限定的类名(Class.forname("类名"))
key2=完全限定的类名(Class.forname("类名"))
key3=完全限定的类名(Class.forname("类名"))
key4=完全限定的类名(Class.forname("类名"))
3.读取属性文件
HashMap和Hashtable
HashMap单线程,线程不安全但速度快
Hashtable多线程,有同步锁线程安全,但速度慢
代理
代理:中间商
设计模式:
一种代理模式:
通过代理对象去访问目标对象,在不改变目标对象的原有的功能的基础之上,对目标对象进行增强 (扩展)目标对象的功能。
原则:
对扩展开放,对修改关闭。
代理分类
1、静态代理
2、动态代理
jdk动态代理
cglib动态代理
静态代理
通过代理方式,给Dao接口的实现类增加日志记录功能?
1、代理类实现目标接口
2、代理类中添加对目标对象的引用
3、测试
目标类和代理类都要实现目标接口
动态代理
jdk动态代理:要求目标对象必须实现指定的接口;
底层使用jdk动态生成目标接口的实现类的实例;动态生成class文件(内存)
cglib动态代理:直接对类进行代理;
动态生成了目标类的子类的代理对象;
如何往一个指定的类中传递参数?
1、将需要传递的参数定义成属性
2、通过构造方法实现对该属性的初始化
3、在类中使用该属性
jdk动态代理实现:
封装类用来生成代理对象
public class JDKProxy implements InvocationHandler {
//声明要代理的目标对象
private Object target;
//通过构造方法完成对目标对象的初始化
public JDKProxy(Object target){
this.target=target;
}
/**
* 产生代理对象
* @return
*/
public Object createProxy(){
//jdk动态生成一个代理对象
//参数1classLoader loader 类加载器,获取目标类的类加载器
//参数2 class<>[] interfaces目标类实现的一一列接口
//参数2 InvocationHandler 对目标方法的拦截处理器,接口,实现该接口的一个对象
Object proxy=(EmpDao) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),this);
return proxy;
}
/**
*
* @param proxy 代理对象
* @param method 目标方法
* @param args 目标方法中使用到的参数
* @return 目标方法调用后返回的结果
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("扩展的功能");
//调用目标方法返回结果
Object object=method.invoke(target,args);
return object;
// return null;
}
}
jdk动态代理实现
封装到一个类中,方法:产生代理对象
1.类JDKProxy2
2.目标对象被代理的对象
3.对目标方法进行扩展(实现InvocationHandle接口)
4.产生代理对象
Peoxy.newProxyInstance()
cglig动态代理
1.引入jar包
2.仿照jdk动态代理的过程
private Object target;
public CgProxy(Object target){
this.target=target;
}
/**
*
* @param o 代理方法
* @param method 目标方法对象
* @param objects 目标方法参数
* @param methodProxy 目标方法代理队形
* @return 目标方法执行后的结果
* @throws Throwable
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("扩展代码");
Object result=methodProxy.invoke(target,objects);
return result;
}
//代理对象
public Object createPorxy(){
//工具类:Enhancer
Enhancer enhancer=new Enhancer();
//设置超类
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
//生成代理对象
Object o = enhancer.create();
return o;
}
测试
public static void main(String[] args) {
EmpService empService=new EmpService();
CgProxy cgProxy=new CgProxy(empService);
EmpService proxy= (EmpService) cgProxy.createPorxy();
proxy.show();