一、Servlet3.0
概念:支持注解开发,由注解配置来代替web.xml配置
用法:在Servlet类上直接使用@WebServlet注解
二、类加载
类的加载概述 :在class文件加载到jvm中时,会对应创建一个Class对象;分为三个步骤:加载、连接、初始化
加载
将class文件加载到内存区域,对应生成一个Class对象
连接
验证: 验证类的结构是否正确
准备 :初始化静态成员
解析 :将字节转换成jvm能够执行的引用(对象、变量、方法)
初始化 就是对变量的初始化
加载时机
创建类对象的实例
访问类的静态变量,或者为静态变量赋值
调用类的静态方法
使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
Class.forName("com.mysql.jdbc.Driver");创建了Driver类的运行时对象
直接使用java.exe命令来运行某个主类
三、类加载器
类加载器的概述 :
将class文件加载进内存,并生成对应的Class对象
类加载器的分类
也被称为引导类加载器,负责Java核心类的加载
比如System,String等。在JDK中JRE的lib目录下rt.jar文件中
加载java中的扩展类,主要加载F:\Program Files\Java\jdk1.8.0_202\jre\lib\ext所有jar包中的类
加载开发人员编写的自定义类、以及一些第三方的jar包中类
负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar 包和类路径
四、类反射机制
概念:通过类的Class对象,动态去调用类中的属性和方法
获取Class对象的方式:
全限定名:包名+类名
Class.forName("全限定名")
编译期(在编译为.class的阶段)
类名.class
运行时
对象名.getClass()
五、反射结合工厂模式
使用继承
解决Apple类、Banana类的代码复用性
Banana、Apple继承Fruit类
使用工厂模式
解决Banana、Apple和其他模块耦合较高
使用反射机制
解决工厂的getFruit方法中if...else代码过多
public static Fruit getFruit(String className) throws Exception { return (Fruit)Class.forName(className).newInstance(); }
六、反射操作构造器(通过构造方法创建对象(构造方法的参数))
概念:使用反射机制操作public、protected、默认、private的构造器
使用构造器创建无参对象
Class<?> c = Class.forName("com.qf.day52.bean.User"); //获取构造器 Constructor<?> constructor = c.getConstructor(); //得到对象 Object o = constructor.newInstance();
使用构造器创建有参对象
Constructor<?> constructor1 = c.getConstructor(String.class,Integer.class,String.class); //构造器中传入数据类型 Object o1 = constructor1.newInstance("阿杰", 20, "男"); //传入参数 System.out.println(o1);
访问非public修饰的构造器
//用getDeclaredConstructor获取全部构造方法 Constructor<?> constructor2 = c.getDeclaredConstructor(String.class,Integer.class); constructor2.setAccessible(true);//暴力反射 Object object = constructor2.newInstance("光芒", 20);
七、反射操作成员变量 (改变属性值)
概念:使用反射机制操作public、protected、默认、private的成员变量
public修饰的成员变量(属性):
必须是public ,protected、default、private 不行
Class<User> userClass = User.class; //获取类对象 User user = userClass.newInstance(); //获取对象 Field name = userClass.getField("name");//获取Field name.set(user,"阿杰");//赋值 System.out.println(user); Object o1 = name.get(user);//通过Field获取赋的值 System.out.println(o1);
非public修饰的成员变量(属性):
Field declaredField = userClass.getDeclaredField("sex"); declaredField.setAccessible(true);//暴力反射 declaredField.set(user,"男");//设置成员变量 System.out.println(user); Object o2 = declaredField.get(user); System.out.println(o2);
八、反射操作成员方法(对方法进行控制)
概念:使用反射机制操作public、protected、默认、private的成员方法
操作public修饰的成员方法
Class<User> userClass = User.class;//获取类对象 User user = userClass.newInstance();//获取对象 Method setAge = userClass.getMethod("setAge", Integer.class);//获取方法 setAge.invoke(user,20);//执行方法
注意:获取的方法要在参数中输入方法名 和参数类型,invoke()中要输入对象和参数
操作非public修饰的成员方法
Method method = userClass.getDeclaredMethod("setName", String.class);//获取全部方法 method.setAccessible(true);//暴力反射 method.invoke(user,"阿杰");//执行方法
九、反射越过泛型检查
概念
java中的泛型的作用范围在编译期,也就是说在运行时,是没有泛型的!
附:运行时对象是没有泛型,通过对象.getClass获得类对象,然后操作
List<Integer> list = new ArrayList<>(); list.add(1); list.add(2); list.add(3); list.add(4); Class<? extends List> listClass = list.getClass();//获取类对象 Method add = listClass.getDeclaredMethod("add",Object.class);//获取方法 add.setAccessible(true);//暴力反射 add.invoke(list,"str");//执行 System.out.println(list);//打印
十、反射通用方法案例
需求:给指定对象的指定属性赋值
步骤:
//获取方法名,通过属性名 :set+属性名第一个字母变大写+后面的属性名
//获得类对象
//获得属性
//获得属性的类型
//获得方法
//执行方法
public static void methods(Object obj, String fields , Object value) throws Exception{ //获取方法名,通过属性名 :set+属性名第一个字母变大写+后面的属性名 String result = "set"+ fields.substring(0,1).toUpperCase() + fields.substring(1); Class<?> c = obj.getClass();//获得类对象 Field field1 = c.getField(fields);//获得属性 Class<?> type = field1.getType();//获得属性的类型 Method method = c.getMethod(result, type);//获得方法 method.invoke(obj,value);//执行方法 }
十一、反射结合配置文件
编写demo.properties,配置对象的唯一标识及对象的全类名,根据这段配置创建一个对象
根据配置文件生成对象
Properties properties = new Properties();//创建properties对象 InputStream resourceAsStream = Demo07.class.getClassLoader().getResourceAsStream("demo.properties");//获取流 properties.load(resourceAsStream);//读取文件 System.out.println(Class.forName(properties.getProperty("demo01")));//获得对象 System.out.println(Class.forName(properties.getProperty("demo02")));
配置文件
demo01=com.qf.day52.bean.Fruit demo02=com.qf.day52.bean.User
十二、静态代理设计模式
概念:增强被代理类的功能
步骤
自定义类实现和被代理类相同的接口(保持方法一致)
在代理类中声明(创建)被代理类的对象(用来调用被代理类对象的方法)
在代理类的方法中使用被代理类调用方法(相当于多了一个中间过程)
代码实现:
public class UserDaoProxy implements UserDao {//实现接口
private UserDao userDao = new UserDaoImpl();//创建对象
@Override
public void insert() {
System.out.println("检测");
userDao.insert();//调用方法
System.out.println("记录日志");
}
@Override
public void delete() {
}
@Override
public void update() {
}
@Override
public void select() {
}
}
特点:
缺点:必须要重写被代理类接口的所有的方法(包括不需要增强的方法,增高了耦合性)
作用:增强被代理类的功能
特点:可以控制被代理类对象