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

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

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

查看所有标签

猜你喜欢:

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

引爆社群

引爆社群

唐兴通 / 机械工业出版社华章科技 / 2015-3 / 49

科技延伸媒介,移动互联网技术催生了微信等各种新的媒体;媒介更新人文,新媒介让互联网重回社群时代;人文重塑商业规则,社群时代的商业模式与法则究竟是怎样的?我们应该如何去适应和应对?本书提出的“新4C法则”为此给出了解决方案。关于如何运用这个法则,本书给出了详尽的阐述。但是,要利用好这个法则,需要我们对它有深入的理解。 场景(Context):移动互联网时代场景为王,所有基于移动互联网的产品和服......一起来看看 《引爆社群》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

随机密码生成器
随机密码生成器

多种字符组合密码