Spring AOP - 通过反射访问存储库自动装配字段
Spring AOP - Access to Repositories autowired field by reflection
这是我第一次在 AspectJ 中可能需要访问存储库的本地私有自动装配字段,以便在>确切<该实例上做一些事情。
我创建了一个切入点,重点关注每个 @Repository
注释 class 的每个方法。当切入点触发时,我得到了当前的 class 实例,我想从中获取 bean
字段。
是这样的:
@Repository
public class MyDao {
@Autowired
private MyBean bean;
public List<Label> getSomething() {
// does something...
}
}
@Aspect
@Component
public class MyAspect {
@Pointcut("within(@org.springframework.stereotype.Repository *)")
public void repositories() {
}
@Before("repositories()")
public void setDatabase(JoinPoint joinPoint) {
try {
Field field = ReflectionUtils.findField(joinPoint.getThis().getClass(), "bean"); // OK since here - joinPoint.getThis().getClass() -> MyDao
ReflectionUtils.makeAccessible(field); // Still OK
Object fieldValue = ReflectionUtils.getField(field, joinPoint.getThis());
System.out.println(fieldValue == null); // true
// should do some stuff with the "fieldValue"
} catch (Exception e) {
e.printStackTrace();
}
}
}
fieldValue
始终是 null
,即使我创建了类似 private | public | package String something = "blablabla";
的内容。
我已确保 "bean" 在应用程序启动时实际实例化(使用调试器验证)。
我关注了How to read the value of a private field from a different class in Java?
我错过了什么? |可能吗? |有什么不同的方法吗?
@springbootlearner 建议采用这种方法access class variable in aspect class
我所要做的就是将 joinPoint.getThis()
替换为 joinPoint.getTarget()
最终的解决方案是:
@Aspect
@Component
public class MyAspect {
/**
*
*/
@Pointcut("within(@org.springframework.stereotype.Repository *)")
public void repositories() {
}
/**
* @param joinPoint
*/
@Before("repositories()")
public void setDatabase(JoinPoint joinPoint) {
Object target = joinPoint.getTarget();
// find the "MyBean" field
Field myBeanField = Arrays.stream(target.getClass().getDeclaredFields())
.filter(predicate -> predicate.getType().equals(MyBean.class)).findFirst().orElseGet(null);
if (myBeanField != null) {
myBeanField.setAccessible(true);
try {
MyBean bean = (MyBean) myBeanField.get(target);// do stuff
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
这是我第一次在 AspectJ 中可能需要访问存储库的本地私有自动装配字段,以便在>确切<该实例上做一些事情。
我创建了一个切入点,重点关注每个 @Repository
注释 class 的每个方法。当切入点触发时,我得到了当前的 class 实例,我想从中获取 bean
字段。
是这样的:
@Repository
public class MyDao {
@Autowired
private MyBean bean;
public List<Label> getSomething() {
// does something...
}
}
@Aspect
@Component
public class MyAspect {
@Pointcut("within(@org.springframework.stereotype.Repository *)")
public void repositories() {
}
@Before("repositories()")
public void setDatabase(JoinPoint joinPoint) {
try {
Field field = ReflectionUtils.findField(joinPoint.getThis().getClass(), "bean"); // OK since here - joinPoint.getThis().getClass() -> MyDao
ReflectionUtils.makeAccessible(field); // Still OK
Object fieldValue = ReflectionUtils.getField(field, joinPoint.getThis());
System.out.println(fieldValue == null); // true
// should do some stuff with the "fieldValue"
} catch (Exception e) {
e.printStackTrace();
}
}
}
fieldValue
始终是 null
,即使我创建了类似 private | public | package String something = "blablabla";
的内容。
我已确保 "bean" 在应用程序启动时实际实例化(使用调试器验证)。
我关注了How to read the value of a private field from a different class in Java?
我错过了什么? |可能吗? |有什么不同的方法吗?
@springbootlearner 建议采用这种方法access class variable in aspect class
我所要做的就是将 joinPoint.getThis()
替换为 joinPoint.getTarget()
最终的解决方案是:
@Aspect
@Component
public class MyAspect {
/**
*
*/
@Pointcut("within(@org.springframework.stereotype.Repository *)")
public void repositories() {
}
/**
* @param joinPoint
*/
@Before("repositories()")
public void setDatabase(JoinPoint joinPoint) {
Object target = joinPoint.getTarget();
// find the "MyBean" field
Field myBeanField = Arrays.stream(target.getClass().getDeclaredFields())
.filter(predicate -> predicate.getType().equals(MyBean.class)).findFirst().orElseGet(null);
if (myBeanField != null) {
myBeanField.setAccessible(true);
try {
MyBean bean = (MyBean) myBeanField.get(target);// do stuff
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}