Springboot整合Hibernate拦截器时无法向拦截器注入Bean

栏目: Java · 发布时间: 6年前

内容简介:根据异常信息,猜测是注入根据异常信息可知,Spring的IoC容器中并没有在

开发环境

JDK 1.8
Springboot 2.1.1.RELEASE

pom配置

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.13</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

关键代码

实体类

@Entity
public class User implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    private String name;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Repository

public interface UserRepository extends JpaRepository<User,Integer> {

}

自定义服务

@Service
public class MyService {

    public void print(){
        System.out.println(this.getClass().getSimpleName()+" call");
    }
}

拦截器

public class SimpleInterceptor extends EmptyInterceptor {

    @Resource
    private MyService myService;

    @Override
    public String onPrepareStatement(String sql) {
        myService.print();
        System.out.println("sql:"+sql);
        return super.onPrepareStatement(sql);
    }
}

启动类

@SpringBootApplication
public class BootHibernateInterceptorProblemApplication {

    public static void main(String[] args) {
        SpringApplication.run(BootHibernateInterceptorProblemApplication.class, args);
    }

}

配置

## DataSource
spring.datasource.url=jdbc:mysql://localhost:3306/demo?characterEncoding=utf8&useSSL=true
spring.datasource.username=root
spring.datasource.password=123456789

## hibernate
spring.jpa.hibernate.ddl-auto=update
## add interceptor
spring.jpa.properties.hibernate.ejb.interceptor=com.rjh.interceptor.SimpleInterceptor

单元测试类

@RunWith(SpringRunner.class)
@SpringBootTest
public class BootHibernateInterceptorProblemApplicationTests {

    @Resource
    private UserRepository userRepository;

    @Test
    public void contextLoads() {
        System.out.println(userRepository.findAll());
    }

}

运行结果

java.lang.NullPointerException
    at com.rjh.interceptor.SimpleInterceptor.onPrepareStatement(SimpleInterceptor.java:20)
    ...
    ...
    ...

分析

根据异常信息,猜测是注入 MyService 失败

修改单元测试

@RunWith(SpringRunner.class)
@SpringBootTest
public class BootHibernateInterceptorProblemApplicationTests {

    @Resource
    private UserRepository userRepository;

    @Resource
    private MyService myService;

    @Resource
    private SimpleInterceptor simpleInterceptor;

    @Test
    public void contextLoads() {
        Assert.assertNotNull(myService);
        Assert.assertNotNull(simpleInterceptor);
        System.out.println(userRepository.findAll());
    }

}

运行结果

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.rjh.interceptor.SimpleInterceptor' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@javax.annotation.Resource(shareable=true, lookup=, name=, description=, authenticationType=CONTAINER, type=class java.lang.Object, mappedName=)}
    ...

分析

根据异常信息可知,Spring的IoC容器中并没有 SimpleInterceptor 这个 Bean ,从此处可知 spring.jpa.properties.hibernate.ejb.interceptor=com.rjh.interceptor.SimpleInterceptor 并没有把这个拦截器注册到Spring容器中

失败方案

SimpleInterceptor 上添加 @Component 注解,将 SimpleInterceptor 注册到Spring容器中。同时注释 spring.jpa.properties.hibernate.ejb.interceptor 配置

失败: SimpleInterceptor 的构造方法触发了两次,添加到 Hibernate 中的 SimpleInterceptor 实例和注册到Spring容器中的 SimpleInterceptor 实例并不是同一个实例

解决方法

增加一个获取Spring的 ApplicationContext 实例的 工具 类,通过这个工具类调用需要注入的服务的方法

工具类

@Component
public class SpringContextUtil implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringContextUtil.applicationContext=applicationContext;
    }

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }
}

修改拦截器

public class SimpleInterceptor extends EmptyInterceptor {

    @Override
    public String onPrepareStatement(String sql) {
        MyService myService= SpringContextUtil.getApplicationContext().getBean(MyService.class);
        myService.print();
        System.out.println("sql:"+sql);
        return super.onPrepareStatement(sql);
    }

}

执行结果

MyService call
sql:select user0_.id as id1_0_, user0_.name as name2_0_ from user user0_
[]

以上所述就是小编给大家介绍的《Springboot整合Hibernate拦截器时无法向拦截器注入Bean》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

三双鞋

三双鞋

[美] 谢家华 / [美] 谢传刚 / 中华工商联合出版社 / 2011-1 / 32.90元

本书是“美捷步”(Zappos)首席执行官谢家华创造奇迹的心路历程与商业哲学的精华萃取,分享了他在商场与生活中得到的宝贵经验与教训。从儿时创办蚯蚓养殖场到大学经营比萨生意,从“链接交换”公司到“美捷步”品牌,本书将谢家华的个人传记与其公司传奇的商业史完美结合,不仅打造了一套利润、激情和目标渐次递进的独特商业模式,更揭示了成功路上起决定作用的真正秘密:奉上幸福。一起来看看 《三双鞋》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具