共计 1690 个字符,预计需要花费 5 分钟才能阅读完成。
问题 1 @Autowired 注入失败
@Autowired
private DingService dingService;
在我的项目中 service 是用 @Autowired 依赖注入,用 debug 测试的时候看到 service 的确为 null。
一开始想法:想用 new 的模式手动生成一个 service,然而在查找材料之后发现这种形式是有弊病的,于是不采纳。
DingServiceImpl dingService1 = new DingServiceImpl();
弊病:在 spring 中如果应用 new 创立一个对象时,这个对象将不在受 spring 管理器治理,这样的话就绕过了容器的依赖注入过程,也可能呈现获取不到应有的属性这种状况。
阐明:Spring 是一个 bean 的容器,由容器负责对象的初始化和依赖注入。当咱们想要从中获取一个 Bean 的实例时,就从 Spring 容器中获取。
最初查找材料之后发现起因:@EntityListeners(LogListener.class)
这里是在 Listener 中应用了 @Autowired,导致的注入失败。
在利用的 Filter 或 Listener 中应用了 @Autowired,注入为空 web 容器启动是依照肯定程序的,即:Listener –> Filter –>Servlet。
因为 Filter 和 Listener 加载程序优先于 spring 容器初始化实例,所以会呈现 null。Spring 的入口就在 Servlet 里。能够用 ApplicationContext 依据 bean 名称(留神名称为实现类而不是接口)去获取 bean。
之前学长就采纳的这种办法:ApplicationContext 去获取 bean。
传送门:https://segmentfault.com/a/11…
这种办法须要新建文件,自定义实现 ApplicationContextAware。
对于 Listener 来说,我找到了一种更不便一点的办法,不须要新建文件来实现类。
@Component
public class LogListener implements ServletContextListener {
@Autowired
private DingService dingService;
@Override
public void contextInitialized(ServletContextEvent sce) {WebApplicationContextUtils.getRequiredWebApplicationContext(sce.getServletContext())
.getAutowireCapableBeanFactory().autowireBean(this);
}
只有继承 ServletContextListener,并在在监听类的 contextInitialized 的办法中加上如上代码即可。
原理是一样的,都是从 ApplicationContext 中获取 bean.
总结一下 @Autowired 为 null 的几种状况:
1. 在利用的 Filter 或 Listener 中应用了 @Autowired
2. 组件下面没有退出了适合的注解。例如:@Service, @Component 等,Bean 没有交付给 Spring 容器。
3. 把 @Autowired 注解加在了一个动态属性上,注入为空。
4. 查看 @Autowired 注入类应用的办法是否为 private,如果为 private 的话在生成动静代理的话 @Autowired 注入的依赖将为空。
5. 查看是不是 new 了一个对象,这样的话就绕过了容器的依赖注入过程,也可能呈现获取不到应有的属性这种状况。
目前对于 ApplicationContext 和 Servlet 这些还不太熟悉,待有理解之后再来补充。长路漫漫。
2. 定时器误差
目前我的项目是 2 分钟发送一次定时工作,并且会判断以后发送工作是否与上次距离 2 分钟,如果是则发送。通过老师的阐明和谷歌的搜寻,才理解这种误差。个别会有 1 到 2 毫秒的提早,写代码的时候须要思考进去这种误差。
3. 双线程导致的问题
解决:在保留前对数据库从新获取最初交互工夫字段