静态内部类访问外部非静态成员
静态内部类访问外部非静态成员
在java中,静态内部类(static nested class)只能访问外部类的静态成员,不能访问外部类的非静态成员。
静态内部类如何访问外部被”@Resource“修饰的非静态成员,该成员变量如下:
@Resource
private TerminalMstMapper terminalMstMapper;
解决思路:@Resource通常用于注入非静态的成员。如果你需要在静态内部类中使用这个成员,那么你应该考虑将外部类的实例传入静态内部类。
方案1:通过外部类实例传递依赖(推荐)
在创建静态内部类对象时,将外部类的依赖(terminalMstMapper)通过构造函数或方法传入。
@Service
public class OutClass {
@Resource
private TerminalMstMapper terminalMstMapper;
public static class StaticInnerClass{
private final TerminalMstMapper terminalMstMapper;
//通过构造函数传入依赖
public StaticInnerClass(TerminalMstMapper mapper){
this.terminalMstMapper = mapper;
}
public void doSomething(){
//可以使用传入的mapper
terminalMstMapper.selectByPrimaryKey(1);
}
}
public void doSomething(){
//创建静态内部类实例
StaticInnerClass innerClass = new StaticInnerClass(this.terminalMstMapper);
innerClass.doSomething();
}
}
方案2:将依赖声明为静态(需谨慎)
如果你的静态内部类只需要访问外部类的静态成员,你可以将外部类的依赖(terminalMstMapper)声明为静态变量,并通过静态方法初始化(需确保线程安全)。
@Service
public class OuterClass {
private static TerminalMstMapper terminalMstMapper; // 静态成员
@Resource
public void setTerminalMstMapper(TerminalMstMapper mapper) {
OuterClass.terminalMstMapper = mapper; // 手动注入到静态变量
}
public static class StaticInnerClass {
public void doSomething() {
// 直接访问静态变量
if (terminalMstMapper != null) {
terminalMstMapper.someMethod();
}
}
}
}
外部类中提供一个静态的方法或字段来访问该Mapper
在外部类中提供一个静态的方法或字段来访问该Mapper,但是同样,这个静态的访问点需要依赖于外部类的实例。
使用@PostConstruct注解来确保在Spring初始化后执行初始化方法,将外部类的实例赋值给静态变量。
@PostConstruct用于标记一个方法,该方法应在依赖注入完成后(如 @Autowired/@Resource 注入结束),构造函数执行之后,对象投入使用前被自动调用。在 Spring 框架中,它也被支持并具有相同的作用。执行顺序如下:
@PostConstruct 是 Spring Bean 生命周期管理的关键注解,它解决了 依赖注入与初始化逻辑的时序问题,确保初始化代码能安全使用所有注入的依赖项。相较于构造函数初始化,它更符合依赖注入的原则,是 Spring 应用中最推荐的初始化方式之一。
@PostConstruct注意事项:
- 方法必须是 void 返回类型;
- 不能是 static 方法,因为 static 方法在类加载时就会执行,而 @PostConstruct 是在 Bean 初始化后执行的;
- 不能有参数;
- 访问权限建议 public(Spring 要求非 private);
@Service
public class ExternalClass {
@Resource
private TerminalMstMapper terminalMstMapper;
private static ExternalClass instance;
@PostConstruct
public void init(){
instance = this;
}
public static TerminalMstMapper getTerminalMstMapper(){
return instance.terminalMstMapper;
}
private static class StaticInnerClass{
public void doSomething(){
TerminalMstMapper mapper = instance.getTerminalMstMapper();
}
}
}
这种方法需要注意:
它使用了静态字段(instance),在Spring中,如果存在多个实例(比如原型作用域),那么instance会被覆盖为最后一个初始化的实例。
通常,我们不推荐使用静态字段来持有Spring Bean,因为这可能导致内存泄漏或状态不一致。
总结
- 方案1更安全:避免了静态变量的线程安全问题,符合依赖注入原则。
- 方案2和方案3的风险:静态变量在并发环境下可能被覆盖,且生命周期与整个应用一致,可能导致内存泄漏。

浙公网安备 33010602011771号