一、谈谈java反射机制:
java反射机制是一种程序运行时自省的机制,提供了在程序运行时动态的操作任何对象的属性和方法的能力。这样不同创建对象,就可以直接调用其中的任意方法。或者动态的获取某个对象的任意属性。而不用在代码中显示的操作属性,增加的程序的灵活性。
二、JAVA反射API:
1、Class类
2、Field类 :通过clazz 对象获取当前类的属性。
3、Method类:通过clazz 对象获取当前类的方法。
4、Constructor类等 :
获取Class对象的方法有:
创建的对象直接 .getClass()。
通过类名.class 获取累的class属性。
调用Class类的.forName("全路径名")方法。
三、动态的创建对象:
public class MainTest {
public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
Class clazz = Person.class;
// 1、反射创建对象
//需要有默认空构造器
Person person1 = clazz.newInstance();
person1.setAge(25);
person1.setName("gaocai");
//根据参数类型返回构造方法,调用构造器的newInstabnce()方法
Constructor constructor = clazz.getConstructor(String.class, Integer.class);
Person person2 = constructor.newInstance("gaocai", 25);
//2、反射获取public属性值 getField() 反射获取private属性值 getDeclaredField()
Field field = clazz.getDeclaredField("name");
// 将私有属性放开权限
field.setAccessible(true);
Object name = field.get(person1);
System.out.println("name = " + name);
field.set(person1, "张三");
//3、动态的执行public方法 getMethod() 动态的执行public方法 getDeclaredMethod()
Method getPerson = clazz.getDeclaredMethod("getPerson");
// 将私有方法放开权限
getPerson.setAccessible(true);
Object invoke = getPerson.invoke(person1);
System.out.println("invoke = " + invoke);
}
public static class Person {
private String name;
private Integer age;
public Person() {
}
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
private String getPerson() {
return name +","+ age;
}
}
}
动态代理是java中的一直动态的创建代理对象,并通过代理的方式来对指定的方法进行增强的一直机制。很多场景都是利用类似机制做到的,比如用来包装 RPC 调用、日志、用户鉴权、全局性异常处理、性能监控,甚至事务处理等。实现动态代理的方式很多,比如 JDK 自身提供的动态代理,就是主要利用了上面提到的反射机制。还有其他的实现方式,比如利用传说中更高性能的字节码操作机制,类似 ASM、cglib(基于 ASM)、Javassist 等。
jdk动态代理:自身提供的动态代理要求被代理对象必须实现接口,才可以使用Proxy.newProxyInstance()方法来实现代理。并实现InvocationHandler接口
接口。
cglib动态代理:代理对象不需要实现接口,但是要求代理对象不是final修饰的,cglib采取的是创建目标类的子类的方式,因为是子类化,我们可以达到近似使用被调用者本身的效果。 使用的是Enhancer.create()方法 并实现MethodInterceptor接口。
四、jdk 动态代理:
jdk的动态代理用到的类是在java.lang.reflect 包下。如Proxy ,invocationHandler ,Method 等
样本代码:
public interface Person {
void eat(String food);
}
public class PersonImpl implements Person {
@Override
public void eat(String food) {
System.out.println("我要吃什么呢?" + food);
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class PersonProxyHandler implements InvocationHandler {
public PersonProxyHandler(T object) {
this.target = object;
}
private final T target;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//1、invocationHandler 是對代理對象的所有方法进行增强 , 需要放过没有增强的方法
Object invoke = null;
//2、要么对指定的方法进行增强,放过其他的方法。
if (method.getName() == "eat") {
System.out.println("方法前");
invoke = method.invoke(target, args);
System.out.println("方法后");
} else {
invoke = method.invoke(target, args);
}
return invoke;
}
}
public static void main(String[] args) {
Person p = new PersonImpl();
PersonProxyHandler h = new PersonProxyHandler(p);
Person personProxy = (Person)Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), PersonImpl.class.getInterfaces(), h);
personProxy.eat("水果");
}
五、cglib 动态代理:
public class CglibPerson {
public void eat(String food) {
System.out.println("我要吃什么呢?" + food);
}
public void sing() {
System.out.println("我在唱歌");
}
}
public void cglibProxyTests() {
CglibPerson person = new CglibPerson();
CglibPerson proxyPerson = (CglibPerson) Enhancer.create(person.getClass(), new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
Object invoke = null;
if ("eat" == method.getName()) {
System.out.println("方法前");
invoke = method.invoke(person, objects);
System.out.println("方法后");
} else {
invoke = method.invoke(person, objects);
}
return invoke;
}
});
proxyPerson.eat("食物");
proxyPerson.sing();
}