目录
一.Java反射
1.1反射的第一步:获取Class类的对象
1.2使用反射获取构造器对象并使用
1.3使用反射获取成员变量对象并使用
1.4使用反射获取成员方法对象并使用
二.代理模式
2.1概述
2.2代理模式在Java中的应用
2.3静态代理
2.4动态代理
2.4.1JDK动态代理
①实现 InvocationHandler 接口,用来做方法拦截
②通过 Proxy.newProxyInstance 创建代理实例
2.4.2cglib动态代理
①实现 MethodInterceptor 接口,用来做方法拦截
②设置父类字节码、拦截处理,获取代理对象
三.注解
3.1元注解
3.2注解的本质
3.3注解的解析
反射指的是允许以编程方式访问已加载类的成分(成员变量、方法、构造器等)。
获取Class对象的三种方式:
获取到构造器对象的作用:依然是初始化对象
setAccessible(boolean)表明反射可以破坏封装性,私有的构造器也可以用来初始化对象
获取到成员变量的作用:依然是为对象赋值、取值
setAccessible(boolean)表明反射可以破坏封装性,私有的属性也可以赋值、取值
获取成员方法的作用:依然是执行方法
setAccessible(boolean)表明反射可以破坏封装性,私有的方法也可以调用执行
二十三种设计模式中的一种,属于结构型模式。它的作用就是通过提供一个代理类,让我们在调用目标 方法的时候,不再是直接对目标方法进行调用,而是通过代理类间接调用。让不属于目标方法核心逻辑 的代码从目标方法中剥离出来——解耦。
意义:目标对象只需要关心自己的实现细节,通过代理对象来实现功能的增强,可以扩展目标对象的功能。体现了非常重要的编程思想:不能随便修改源码,如果需要修改源码,通过修改代理的方式来实现功能的拓展。
案例:给添加学生的service里增强事务操作
IStudentService
StudentServiceImpl(需要被代理的对象)
ProxyStudent(代理对象)
静态代理的缺点
在不改变原有功能代码的前提下,能够动态的实现方法的增强
invoke方法:代理对象要执行的方法,实现目标方法的执行和功能增强
saveProxyClass用于 生成代理类的字节码文件
private void saveProxyClass(String path){
byte[] $proxy1s = ProxyGenerator.generateProxyClass("$Proxy1",
StudentServiceImpl.class.getInterfaces());
FileOutputStream outputStream=null;
try {
outputStream=new FileOutputStream(path+"$Proxy1.class");
outputStream.write($proxy1s);
} catch (Exception e) {
e.printStackTrace();
}finally {
if(outputStream!=null){
try {
outputStream.flush();
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
我们可以看一下生成的代理类,可以发现代理类继承了 Proxy 并实现了目标类实现的所有接口,然后通过反射获取了目标方法的对象
JDK动态代理有一个前提,需要代理的类必须实现接口,如果没有实现接口,只能通过CGLIB来实现,其实就是对于JDK动态代理的一个补充
我们可以看一下生成的代理类
Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制。 Java 语言中的类、构造器、方法、成员变量、参数等都可以被注解进行标注。
JDK中内置的一些注解:
自定义注解:
@Target(ElementType.TYPE)//类级别,元注解
@Retention(RetentionPolicy.RUNTIME)//自定义注解的存活范围,元注解
public @interface Check {
public int value() default 1;
}
元注解:用于描述注解的注解
我们先用 javac 对 Check.java 进行编译,然后再用 javap 对 Check.class 进行反编译,查看其源代码。
可以发现,注解的本质上就是一个接口,该接口默认继承 Annotation 接口。注解中的属性即为接口中的抽象方法。
特别注意注解中的属性返回类型是有限制的,只能是如下的类型:
注解的解析就是判断是否存在注解,存在注解就解析出内容。注解在哪个成分上,我们就先拿哪个成分对象。
与注解解析相关的接口
AnnotatedElement:该接口定义了与注解解析相关的解析方法
所有的类成分Class, Method , Field , Constructor,都实现了AnnotatedElement接口,他们都拥有解析注解的能力
案例:获取自定义注解的className和methodName,执行该方法
自定义注解 Pro
获取上边的注解对象,其实就是在内存中生成了一个实现该注解接口的实现对象
public class ProImpl implements Pro{
@Override
public String methodName() {
......
return "com.annotation.parse.Print";//返回使用注解时传的参数
}
@Override
public String className() {
......
return "print";//返回使用注解时传的参数
}
}