https://note.youdao.com/ynoteshare/index.html?id=75a5a9c30785e57c55b5a188df271f95&type=note&_time=1641737823295
反射技术
反射的基本的概念
使用反射机制可以动态获取当前class的信息 比如方法的信息、注解信息、方法的参数、属性等;
反射技术应用的场景
- JDBC加载驱动连接 class.forname
- Spring容器框架IOC实例化对象
- 自定义注解生效(反射+Aop)
- 第三方核心的框架
反射技术的使用
Class类 代表类的实体,在运行的Java应用程序中表示类和接口
Field类 代表类的成员变量(成员变量也称为类的属性)
Method类 代表类的方法
Constructor类 代表类的构造方法
使用反射机制初始化对象 获取当前class的信息
Class<?> aClass = Class.forName("com.mayikt.entity.UserEntity");
执行无参数构造函数
Class<?> aClass = Class.forName("com.mayikt.entity.UserEntity");
UserEntity userEntity = (UserEntity) aClass.newInstance();
userEntity.setName("mayikt");
userEntity.setUserId(1234);
System.out.println(userEntity);
执行有参数构造函数
Class<?> aClass = Class.forName("com.mayikt.entity.UserEntity");**
// 执行有参数构造函数
Constructor<?> constructor = aClass.
getConstructor(Integer.class, String.class);
UserEntity userEntity = (UserEntity) constructor.
newInstance(10, "mayikt");
System.out.println(userEntity);
使用反射机制给属性赋值
Class<?> aClass = Class.forName("com.mayikt.entity.UserEntity");
// 给私有属性赋值
UserEntity userEntity = (UserEntity) aClass.newInstance();
Field userId = aClass.getDeclaredField("userId");
userId.setAccessible(true);
userId.set(userEntity,12);
Field name = aClass.getDeclaredField("name");
name.setAccessible(true);
name.set(userEntity,"mayikt");
System.out.println(userEntity);
Exception in thread "main" java.lang.IllegalAccessException: Class com.mayikt.Test001 can not access a member of class com.mayikt.entity.UserEntity with modifiers "private"
at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296)
如果使用反射给私有属性或者调用私有的方法 都需要设置权限
使用反射机制给调用方法
Class<?> aClass = Class.forName("com.mayikt.entity.UserEntity");
// 给私有属性赋值
UserEntity userEntity = (UserEntity) aClass.newInstance();
Method meite = aClass.getDeclaredMethod("meite", Integer.class);
meite.setAccessible(true);
Object invoke = meite.invoke(userEntity, 10);
System.out.println(invoke);
获取自定义注解
field.getAnnotation();
Class dtoClass = formFillingStatisticsResDto.class;
List<Field> fieldList = Arrays.stream(dtoClass.getDeclaredFields())
.filter(t -> t.getAnnotation(QueryResult.class) != null)
.collect(Collectors.toList());
formFillingStatisticsResDto checkFormFillingStatisticsResDto = new formFillingStatisticsResDto();
formFillingStatisticsResDto .setCheckPointName("汇总");
formFillingStatisticsResDto .setDutyName("/");
private void buildSumCheckformllingStatisticResdtoList(List<formFillingStatisticsResDto> statisticsResDtoList) {
Class dtoClass = formFillingStatisticsResDto.class;
List<Field> fieldList = Arrays.stream(dtoClass.getDeclaredFields())
.filter(t -> t.getAnnotation(QueryResult.class) != null)
.collect(Collectors.toList());
formFillingStatisticsResDto formFillingStatisticsResDto = new formFillingStatisticsResDto ();
formFillingStatisticsResDto.setCheckPointName("汇总");
checkFormFillingStatisticsResDto.setDutyName("/");
fieldList.forEach(field -> {
String filedName = field.getName();
try {
long sum = 0;
for (CheckFormFillingStatisticsResDto checkFormFillingStatistics : statisticsResDtoList) {
Method getMethod = dtoClass.getMethod("get" + filedName.substring(0, 1).toUpperCase() + filedName.substring(1, filedName.length()));
sum = sum + (Long) getMethod.invoke(checkFormFillingStatistics);
}
Method dtoSetMethod = dtoClass.getMethod("set" + filedName.substring(0, 1).toUpperCase() + filedName.substring(1, filedName.length()), Long.class);
dtoSetMethod.invoke(formFillingStatisticsResDto , Long.valueOf(sum));
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
});
statisticsResDtoList.add(checkFormFillingStatisticsResDto);
}
自定义注解
什么是注解
Java注解是Jdk1.5推出一个重大特性 可以标记在类、方法、属性上面
内置注解:
1.@Override - 检查该方法是否是重写方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。
2.@Deprecated - 标记过时方法。如果使用该方法,会报编译警告。
元注解:
@Retention - 标识这个注解怎 么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。
@Documented - 标记这些注解是否包含在用户文档中。
@Target - 标记这个注解应该是哪种 Java 成员。
@Inherited - 标记这个注解是继承于哪个注解类(默认 注解并没有继承于任何子类)
注解如何生效
- 通过Aop技术+反射技术
- 反射类+filed.getAnnotation 获取指定字段进行操作
t.getAnnotation(QueryResult.class)
自定义注解
//----------------------------------------------------------------*/
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//自定义一个注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ExtTransactional {
String name();
}
实体类
package com.mayikt.entity;
import com.mayikt.ExtTransactional;
import lombok.Data;
/**
* @ClassName UserEntity
* @Author 蚂蚁课堂余胜军 QQ644064779 www.mayikt.com
* @Version V1.0
**/
@Data
public class UserEntity {
private Integer userId;
private String name;
public UserEntity(){
System.out.println("###我是无参构造函数###");
}
public UserEntity(Integer userId, String name) {
this.userId = userId;
this.name = name;
}
@ExtTransactional(name ="mayikt")
private String meite(Integer a){
System.out.println("meite:"+a);
return "meite66";
}
}
反射获取
Class<?> aClass = Class.forName("com.mayikt.entity.UserEntity");
UserEntity userEntity = (UserEntity) aClass.newInstance();
Method meite = aClass.getDeclaredMethod("meite", Integer.class);
meite.setAccessible(true);
ExtTransactional declaredAnnotation = meite.getDeclaredAnnotation(ExtTransactional.class);
System.out.println(declaredAnnotation.name());
Spring中事务的类型
- 手动事务
- 声明式事务 基于注解+aop实现
注解自定义 生效+aop+反射技术生效
原理:
AOP技术:
1.AOP技术 在方法前后 拦截
2.前置通知 后置通知 环绕通知 异常通知
3.AOP技术 环绕通知 在我们目标方法之前开启事务 目标方法执行完毕 提交事务或者回滚
事务的原理
手动事务
自定义事务注解
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
@Component
public class TransactionalUtils {
@Autowired
private DataSourceTransactionManager dataSourceTransactionManager;
/**
* begin
* @return
*/
public TransactionStatus begin(){
// 设置传播行为
TransactionStatus transaction =
dataSourceTransactionManager.getTransaction(new DefaultTransactionAttribute());
return transaction;
}
/**
* 提交
* @param transaction
*/
public void commit( TransactionStatus transaction){
dataSourceTransactionManager.commit(transaction);
}
/**
* 回滚
* @param transaction
*/
public void rollback(TransactionStatus transaction){
dataSourceTransactionManager.rollback(transaction);
}
}
@GetMapping("/insertUser")
public String insertUser(UserEntity userEntity){
TransactionStatus begin=null;
try {
begin = transactionalUtils.begin();
int j = 1 / userEntity.getUserId();
String result = userMapper.insertUser(userEntity) > 0 ? "success" : "fail";
transactionalUtils.commit(begin);
return "success";
}catch (Exception e){
if(begin!=null){
transactionalUtils.rollback(begin);
}
return "fail";
}
}
Aop切面类
package com.mayikt.aop;
import com.mayikt.utils.TransactionalUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
/**
* 基于aop
*/
@Aspect
@Component
public class ExtTransactionalAop {
@Autowired
private TransactionalUtils transactionalUtils;
@Around(value = "@annotation(com.mayikt.aop.ExtTransactional)")
public Object around(ProceedingJoinPoint joinPoint) {
TransactionStatus begin = null;
try {
begin = transactionalUtils.begin();
Object result = joinPoint.proceed();
transactionalUtils.commit(begin);
return result;
} catch (Throwable throwable) {
if (begin != null)
transactionalUtils.rollback(begin);
return "fail";
}
}
}