一、类型信息
运行时类型信息使得你可以在程序运行时发现和使用类型信息。
在C语言中叫做typeId,在Java中我们在创建每个类对象后,都给这个类一个Class类型信息属性.Class类的toString方法里面就是获取类型加上全类名:
public String toString() {
return (isInterface() ? "interface " : (isPrimitive() ? "" : "class "))
+ getName();
}
二、基于类型信息进行判断
Class<Shape> clazz = Shape.class;
Class<Area> areaClass = Area.class;
boolean flag = areaClass.isAssignableFrom(clazz);
Shape类 implement Area接口
isAssignableFrom 是用来判断一个类Class1和另一个类Class2是否相同或是另一个类的超类或接口。
instanceof 是用来判断一个对象实例是否是一个类或接口的或其子类子接口的实例。
三、常用Class的API
Class clazz = Class.forName("com.abc.qwe.model.Shape");
//获取当前clazz对象上的注解
Annotation[] annotations = clazz.getAnnotations();
//获取当前clazz对象 实现的接口
Class<?>[] interfaces = clazz.getInterfaces();
//通过带参构造方法创建实例对象
ReflectServiceImpl rsi = (ReflectServiceImpl)Class.forName("com.xxx.ReflectServiceImpl").getConstructor(String.class).newInstance("李四");
四、动态代理
自定义JDK动态代理
1、编写动态代理类实现InvocationHandler接口
/**
* 自定义动态代理类 在当前的动态代理类中 编写需要 添加的操作
*/
public class DynamicProxyClass implements InvocationHandler {
//将要被代理的对象
private Object proxied;
public DynamicProxyClass(Object proxied) {
//在自定义的动态代理构造方法中 为成员变量赋值
this.proxied = proxied;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//第一步做的事情是 将被代理的类信息进行打印
System.out.println("被代理类的typeId:" + proxy.getClass());
System.out.println("被代理的方法:"+method.getName());
System.out.println("被代理方法的参数长度:"+(args==null?0:args.length));
return method.invoke(proxied,args);
}
}
2、创建动态代理对象
SourceInterface proxy= (SourceInterface)Proxy.newProxyInstance(SourceInterface.class.getClassLoader(),new Class[]{SourceInterface.class},new DynamicProxyClass(new ImplementClass()));
3、调用动态代理对象
public static void customer(SourceInterface sourceInterface) {
sourceInterface.doSomething();
sourceInterface.method();
}
4、结果展示
这时会在基本实现类方法基础上添加动态代理类里面编写的代码。
5、cglib动态代理
cglib动态代理是 org.springframework.cglib.proxy 包下的。
实现cglib动态代理的机制与jdk的动态代理有所不同。
jdk动态代理是基于接口,创建一个并行的新的代理子类实现代理。
cglib是通过将需要代理的对象作为父类,创建被代理类子类的代理对象。
cglib需要实现MethodInterceptor接口,创建Enhancer增强类对象实现。
代码如下:
public class CglibProxyExample implements MethodInterceptor {
/**
* 获取当前类的动态代理对象
* @param source
* @return
*/
public Object getProxy(Class source) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(source);
enhancer.setCallback(this);
Object proxy = enhancer.create();
return proxy;
}
/**
*
* @param proxy
* @param method
* @param args
* @param methodProxy
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("进入Cglib动态代理方法");
Object result = methodProxy.invokeSuper(proxy,args);
System.out.println("在方法之后执行");
return result;
}}
五、总结
我们在实际开发过程中要多利用反射的方法,编写灵活性更强的代码。
例如我们结合泛型
List<? extends Object> list
能够灵活的根据不同的实现类调用不同的覆写方法。