Java反射机制
运行状态中,对于任意一个类能获取与调用这个类的属性、方法。
1.获取Class
Class userClass1 = new USer().getClass();
Class userClass2 = User.class;
Class userClass3 = Class.forName("com.jun.entity.User");
2.Class重要模块
// 获取Class
Class userClass =Class.forName("com.jun.entity.User");
//调用无参数构造方法.
Object = userClass.newInstance();
// 获取Class
Class userClass = User.class;
// 获取构造方法
Constructor[] constructor = userClass.getConstructors();
// 获取属性
Field[] fields = userClass.getDeclaredFields();
// 获取方法
Method[] methods = userClass.getMethods();
3.Class类、Field类、Method类、Constructor类
Class类方法
public T newInstance() 创建对象
public String getName() 返回完整类名带包名
public String getSimpleName() 返回类名
public Field[] getFields() 返回类中public修饰的属性
public Field[] getDeclaredFields() 返回类中所有的属性
public Field getDeclaredField(String name) 根据属性名name获取指定的属性
public native int getModifiers() 获取属性的修饰符列表,返回的修饰符是一个数字,每个数字是修饰符的代号【一般配合Modifier类的toString(int x)方法使用】
public Method[] getDeclaredMethods() 返回类中所有的实例方法
public Method getDeclaredMethod(String name, Class<?>… parameterTypes) 根据方法名name和方法形参获取指定方法
public Constructor<?>[] getDeclaredConstructors() 返回类中所有的构造方法
public Constructor getDeclaredConstructor(Class<?>… parameterTypes) 根据方法形参获取指定的构造方法
public native Class<? super T> getSuperclass() 返回调用类的父类
public Class<?>[] getInterfaces() 返回调用类实现的接口集合
Field类方法
public String getName() 返回属性名
public int getModifiers() 获取属性的修饰符列表,返回的修饰符是一个数字,每个数字是修饰符的代号【一般配合Modifier类的toString(int x)方法使用】
public Class<?> getType() 以Class类型,返回属性类型【一般配合Class类的getSimpleName()方法使用】
public void set(Object obj, Object value) 设置属性值
public Object get(Object obj) 读取属性值
Method类方法
public String getName() 返回方法名
public int getModifiers() 获取方法的修饰符列表,返回的修饰符是一个数字,每个数字是修饰符的代号【一般配合Modifier类的toString(int x)方法使用】
public Class<?> getReturnType() 以Class类型,返回方法类型【一般配合Class类的getSimpleName()方法使用】
public Class<?>[] getParameterTypes() 返回方法的修饰符列表(一个方法的参数可能会有多个。)【结果集一般配合Class类的getSimpleName()方法使用】
public Object invoke(Object obj, Object… args) 调用方法
Constructor类方法
public String getName() 返回构造方法名
public int getModifiers() 获取构造方法的修饰符列表,返回的修饰符是一个数字,每个数字是修饰符的代号【一般配合Modifier类的toString(int x)方法使用】
public Class<?>[] getParameterTypes() 返回构造方法的修饰符列表(一个方法的参数可能会有多个。)【结果集一般配合Class类的getSimpleName()方法使用】
public T newInstance(Object … initargs) 创建对象【参数为创建对象的数据】
动态代理
一、JDK动态代理
JDK动态代理只支持接口代理。
InvocationHandler 通过invoke()方法反射来调用目标类中的代码,动态地将横切逻辑和业务编织在一起,
Proxy利用 InvocationHandler动态创建一个符合某一接口的的实例, 生成目标类的代理对象。
如果代理类没有实现 InvocationHandler 接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。
/**
* 目标接口
*/
public interface JunService {
public void testJdkProxy(int topicId);
}
/**
* 目标接口实现
*/
public class JunServiceImple implements JunService {
@Override
public void testJdkProxy(int topicId) {
System.out.println("");
System.out.println("----------逻辑实现: "+topicId);
System.out.println("");
}
}
/**
* 代理
*/
public class JunJdkHandle implements InvocationHandler {
// 目标(被代理的接口)
private Object object;
// 指定目标
public JunJdkHandle(Object object) {
this.object=object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//业务逻辑代码
System.out.println("---JDK代理开始---");
System.out.println("---method: "+method.toString());
System.out.println("---args: "+args.toString());
//通过Java反射机制调用业务类的目标方法
Object obj = method.invoke(object, args);
//业务逻辑代码
System.out.println("---JDK代理结束---");
return obj;
}
}
public class Test01 {
public static void main(String[] args) {
// 创建被代理的 目标接口
JunService target = new JunServiceImple();
// 将目标接口 传入 代理
JunJdkHandle junhandle = new JunJdkHandle(target);
// 接口创建代理实例。
// 参数: 类加载器、目标接口、代理类
JunService junService = (JunService) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
junhandle);
// 调用接口
junService.testJdkProxy(9999999);
}
}
结果:
---JDK代理开始---
---method: public abstract void com.south.aop.jdk.JunService.testJdkProxy(int)
---args: [Ljava.lang.Object;@65b54208
----------逻辑实现: 9999999
---JDK代理结束---
二、Cglibd动态代理
在运行时动态的生成指定类的子类对象,覆盖其中特定方法并添加增强代码,从而实现AOP。
通过继承方式做动态代理,如果某个类被标记为final,是无法用CGLIB做动态代理的。
1.引入依赖
<!-- cglib依赖 -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.1</version>
</dependency>
2.代码实现
/**
* 接口(父类)
*/
public interface JunService {
public void testCglibProxy(int topicId);
}
/**
* 实现(子类)
*/
public class JunServiceImple implements JunService {
@Override
public void testCglibProxy(int topicId) {
System.out.println("");
System.out.println("------------------实际实现方法: "+topicId);
System.out.println("");
}
}
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* 代理类
*/
public class JunCglibProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
//
public Object getProxy(Class clazz) {
// 设置需要创建子类的类
enhancer.setSuperclass(clazz);
//
enhancer.setCallback(this);
// 通过字节码技术动态创建子类实例
return enhancer.create();
}
//拦截所有父类方法
// Object目标类实例, Method目标类方法的反射对象, Object[]方法的动态入参, MethodProxy代理类
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy proxy) throws Throwable {
System.out.println("CGLib动态代理开始");
System.out.println("------参数 arg1: "+arg1.toString());
// 通过代理类调用父类的方法
Object result = proxy.invokeSuper(arg0, arg2);
System.out.println("CGLib动态代理结束");
return result;
}
}
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* 代理类
*/
public class JunCglibProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
//
public Object getProxy(Class clazz) {
// 设置需要创建子类的类
enhancer.setSuperclass(clazz);
//
enhancer.setCallback(this);
// 通过字节码技术动态创建子类实例
return enhancer.create();
}
//拦截所有父类方法
// Object目标类实例, Method目标类方法的反射对象, Object[]方法的动态入参, MethodProxy代理类
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy proxy) throws Throwable {
System.out.println("CGLib动态代理开始");
System.out.println("------参数 arg1: "+arg1.toString());
// 通过代理类调用父类的方法
Object result = proxy.invokeSuper(arg0, arg2);
System.out.println("CGLib动态代理结束");
return result;
}
}
public class Tste02 {
public static void main(String [] args) {
// 创建代理类
JunCglibProxy junCglibProxy = new JunCglibProxy();
// 参数: 监视子类
JunService form = (JunService) junCglibProxy.getProxy(JunServiceImple.class);
form.testCglibProxy(99999);
}
}
结果:
CGLib动态代理开始
------参数 arg1: public void com.south.aop.cglib.JunServiceImple.testCglibProxy(int)
------------------实际实现方法: 99999
CGLib动态代理结束
AOP的应用
记录日志(调用方法后记录日志) 监控性能(统计方法运行时间) 权限控制(调用方法前校验是否有权限) 事务管理(调用方法前开启事务,调用方法后提交关闭事务) 缓存优化(第一次调用查询数据库,将查询结果放入内存对象,第二次调用,直接从内存对象返回,不需要查询数据库)
1.引入依赖
<!-- AOP依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.7.8</version>
</dependency>
2.代码实现
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.json.JSONObject;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class JunAspect {
// 监听方法
@Pointcut("execution(* com.south.controller.*.*(..))")
public void pointCutExecution() {
}
// 监听注解 @PermissionsAnnotation
@Pointcut("@annotation(com.south.controller.*.PermissionsAnnotation)")
private void pointCutAnnotation() {
}
@Around("pointCutAnnotation()")
public Object pointCutExecution(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("===================开始增强处理===================");
//获取请求参数,详见接口类
Object[] objects = joinPoint.getArgs();
Long id = ((JSONObject) objects[0]).getLong("id");
String name = ((JSONObject) objects[0]).getString("name");
System.out.println("id1->>>>>>>>>>>>>>>>>>>>>>" + id);
System.out.println("name1->>>>>>>>>>>>>>>>>>>>>>" + name);
// 修改入参
JSONObject object = new JSONObject();
object.put("id", 8);
object.put("name", "lisi");
objects[0] = object;
// 将修改后的参数传入
return joinPoint.proceed(objects);
}
/**
* 在上面定义的切面方法之前执行该方法
*/
@Before("pointCutExecution()")
public void doBefore(JoinPoint joinPoint) {
// 获取签名
Signature signature = joinPoint.getSignature();
// 获取切入的包名
String declaringTypeName = signature.getDeclaringTypeName();
// 获取即将执行的方法名
String funcName = signature.getName();
}
/**
* 在上面定义的切面方法之后执行该方法
*/
@After("pointCutExecution()")
public void doAfter(JoinPoint joinPoint) {
Signature signature = joinPoint.getSignature();
String method = signature.getName();
}
/**
* 在上面定义的切面方法返回后执行该方法,可以捕获返回对象或者对返回对象进行增强。
*/
@AfterReturning(pointcut = "pointCutExecution()", returning = "result")
public void doAfterReturning(JoinPoint joinPoint, Object result) {
Signature signature = joinPoint.getSignature();
String classMethod = signature.getName();
}
}