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

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

内容简介:根据异常信息,猜测是注入根据异常信息可知,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》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

海量运维、运营规划之道

海量运维、运营规划之道

唐文 / 电子工业出版社 / 2014-1-1 / 59.00

《海量运维、运营规划之道》作者具有腾讯、百度等中国一线互联网公司多年从业经历,书中依托工作实践,以互联网海量产品质量、效率、成本为核心,从规划、速度、监控、告警、安全、管理、流程、预案、考核、设备、带宽等方面,结合大量案例与读者分享了作者对互联网海量运维、运营规划的体会。 《海量运维、运营规划之道》全面介绍大型互联网公司运维工作所涉及的各个方面,是每个互联网运维工程师、架构师、管理人员不可或......一起来看看 《海量运维、运营规划之道》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

URL 编码/解码
URL 编码/解码

URL 编码/解码

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具