反射(框架的灵魂)
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
类的加载过程:
程序经过javac.exe命令后,会生成多个字节码文件,经过java.exe命令,对字节码文件解释运行,相当于将字节码文件加载到内存中,此过程叫做类的加载,加载到内存中的类,叫运行时类,此运行时类就是Class类的实例。
类加载器:
将字节码加载到内存中,用到了类加载器(类装载器),将这些静态数据(字节码)转换成方法区中的运行时数据结构,然后在堆中生成一个代表这个类的java.lang.Class对象,作为方法区中的类数据的入口
类缓存:
标准的JavaSE类加载器可以按要求查找类,一旦某个类被类加载器加载中,它将维持(缓存)加载一段时间,不过jvm回收机制可以回收这些缓存对象
类加载器分类(ClassLoader)
bootstrap classloader:启动类加载器,加载rt.jar中的类;
Extension ClassLoader:扩展类加载器,加载jre/lib/ext目录下的类;
System ClassLoader:应用程序类加载器,加载CLASSPATH下的类,自己写的类
还有一个,用户自定义类加载器,实现ClassLoader接口,自定义加载规则。
通常情况下,Java中所有类都是通过前三个类加载器加载的。
类加载器之间存在上下级关系,系统类加载器的上级是扩展类加载器,而扩展类加载器的上级是引导类加载器。
获取Class对象的四种方式
public class TestDemo {
public static void main(String[] args) {
//.class
Class<Person> personClass1 = Person.class;
//class cn.wu.www.Person
System.out.println(personClass1);
//getClass()
Person person = new Person();
Class<? extends Person> personClass2 = person.getClass();
//class cn.wu.www.Person
System.out.println(personClass2);
//forName(String str)
try {
Class<?> forName = Class.forName("cn.wu.www.Person");
System.out.println(forName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//ClassLoader()
try {
ClassLoader classLoader = TestDemo.class.getClassLoader();
Class<?> loadClass = classLoader.loadClass("cn.wu.www.Person");
System.out.println(loadClass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
通过反射,创建运行时类的对象
@Test
public void test1(){
try {
Class<Person> personClass = Person.class;
Person person = personClass.newInstance();
System.out.println(person);
} catch (InstantiationException e) {
//此异常指的时构造器的权限要高于private
e.printStackTrace();
} catch (IllegalAccessException e) {
//必须有空参构造器
e.printStackTrace();
}
}
静态代理:代理类对象在编译期间就确立下来,不宜程序再次修改,一个代理类只能为一个接口服务
动态代理:在程序运行时运用反射机制动态创建代理类对象。
动态代理是什么?有哪些应用?
当想要给实现了某个接口的类中的方法,加一些额外的处理。比如说加日志,加事务等。可以给这个类创建一个
代理,故名思议就是创建一个新的类,这个类不仅包含原来类方法的功能,而且还在原来的基础上添加了额外处
理的新类。这个代理类并不是定义好的,是动态生成的。具有解耦意义,灵活,扩展性强。
动态代理的应用:
Spring的AOP
加事务
加权限
加日志
反射应用:动态代理
public interface Human {
String getBelief();
void eat(String food);
}
public class SuperMan implements Human {
@Override
public String getBelief() {
return "Fly";
}
@Override
public void eat(String food) {
System.out.println("我喜欢吃" + food);
}
}
public class MyInvocationHandler implements InvocationHandler {
//需要使用被代理类对象进行赋值
private Object obj;
public void bind(Object obj) {
this.obj = obj;
}
/**
* @param proxy 代理类对象
* @param method 代理类对象方法
* @param args 参数
* @return 被代理类方法的返回值
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(obj, args);
}
}
public class ProxyFactory {
/**
* @param obj:被代理对象
* @return 返回一个代理类对象
*/
public static Object getProxyFactory(Object obj) {
MyInvocationHandler myInvocationHandler = new MyInvocationHandler();
myInvocationHandler.bind(obj);
/**
* 第一个:被加载的类
* 第二个:要实现的接口们
* 第三个:代理对象所有的方法都会调用InvocationHandler接口实现类的invoke()方法(除了getClass()方法之外)
*/
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), myInvocationHandler);
}
}
public class TestDemo {
public static void main(String[] args) {
//代理类对象
SuperMan superMan = new SuperMan();
//得到被代理类对象
Human proxyFactory = (Human) ProxyFactory.getProxyFactory(superMan);
//被代理类调用方法(实际上事调用了代理类的方法)
System.out.println(proxyFactory.getBelief());
proxyFactory.eat("香蕉");
}
}