将Spring-mananged bean注入Hibernate的实体

时间:2017-12-11 23:41:24

标签: java spring hibernate aspectj spring-data-rest

这不会起作用(方面编织) - SlugGenerator.slugger 仍为 null 。请有人看看这个并给我一个帮助吗?

  1. 我的想法是将spring的服务编织到实体的价值生成器中。我知道我可以使用实体的加载事件来注入该依赖项。
  2. 我仔细检查过Slugify组件是否被Spring正确实例化(我可以成功地将它注入控制器)。
  3. Category.java(entity - domain object):

    @Entity(name = "Category")
    @Table(name = "category")
    @Data
    public class Category
    {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
        @GeneratorType(type = SlugGenerator.class, when = GenerationTime.ALWAYS)
        private String slug;
    
        // ...
    }
    

    SlugGenerator.java(值生成器 - 由Hibernate实例化):

    @NoArgsConstructor
    @Configurable(autowire = Autowire.BY_TYPE)
    public class SlugGenerator implements ValueGenerator<String>
    {
        @Autowired
        private Slugify slugger;
    
        @Override
        public String generateValue(Session session, Object owner) {
            Category category = (Category) owner;
    
            return slugger.slugify(category.getTitle());
        }
    }
    

    Slugify.java(Spring管理的服务):

    @Component
    public class SlugifyImpl implements Slugify {
        @Override
        public String slugify(String input)
        {
            // ...
        }
    }
    

    DispatcherConf.java(Spring conf。):

    public class DispatcherConf extends AbstractAnnotationConfigDispatcherServletInitializer {
        @Override
        protected Class<?>[] getRootConfigClasses() {
            return new Class[] {ApplicationConf.class};
        }
    
        @Override
        protected Class<?>[] getServletConfigClasses() {
            return new Class[] {WebConf.class};
        }
    
        @Override
        protected String[] getServletMappings() {
            return new String[] {"/*"};
        }
    }
    

    ApplicationConf.java(Spring conf。):

    @Configuration
    @EnableSpringConfigured
    @Import({DataConf.class})
    @ComponentScan(basePackages = {
            "pl.xxx.api.utils",
    })
    public class ApplicationConf
    {
        @Bean
        public RepositoryRestConfigurer repositoryRestConfigurer() {
            return new RepositoryRestConfigurerAdapter() {
                @Override
                public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
                    config.setBasePath("/api");
                }
            };
        }
    }
    

    WebConf.java(Spring conf。):

    @Import(RepositoryRestMvcConfiguration.class)
    public class WebConf {
    }
    

    的build.gradle:

    // ...
    compile "org.springframework:spring-aspects:$springAspects"
    // ...
    

    jvm classpath(以及其他):

    aspectjrt-1.8.13.jar
    

    的IntelliJ:

    Build,Execution,Deployment > Compiler > Annotation Processors > Enable Annotation Processing set to TRUE
    

2 个答案:

答案 0 :(得分:0)

感谢@NándorElődFekete的评论,我明白了如何实现我的目标 - 将Spring管理的bean注入到新的运营商创建的实例中。

我是如何做到的:

请考虑以下注意事项:

  • 无法将bean注入ValueGenerator实现(SlugGenerator.java) - 为什么我不知道。这是一个 公开问题:)

  • 我已成功将Slugify bean注入实体(Category.java)。

在Spring的配置中,我只使用了@EnableSpringConfigured。

我选择使用加载时间wevaing(LTW),因此我在Glassfish域的配置文件中添加了以下行:

<jvm-options>-javaagent:/usr/local/lib/java/aspectjweaver-1.8.13.jar</jvm-options>

Category.java:

@Entity(name = "Category")
@Table(name = "category")
@Data
@Configurable(autowire = Autowire.BY_TYPE)
public class Category
{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @GeneratorType(type = SlugGenerator.class, when = GenerationTime.ALWAYS)
    private String slug;

    @Autowired
    @Transient
    private Slugify slugGenerator;
    // ...
}

class SlugGenerator implements ValueGenerator<String>
{
    @Override
    public String generateValue(Session session, Object owner) {
        Category category = (Category) owner;
        Slugify slugGenerator = category.getSlugGenerator();

        return slugGenerator.slugify(category.getName());
    }
}

Voila,私有属性slugGenerator填充了Slugify接口的bean:)

答案 1 :(得分:-1)

也许这种方法会有所帮助:

@Component
public final class MyBeanUtils {

    @Autowired private ApplicationContext ctx;

    private static MyBeanUtils instance;

    @PostConstruct
    private void registerInstance() {
        instance = this;
    }

    public static <T> T getBean(Class<T> clazz) {
        return instance.ctx.getBean(clazz);
    }

    public static ApplicationContext appCtx() {
        return instance.ctx;
    }
}

然后在非托管类中使用Spring bean,例如:

public class SlugGenerator implements ValueGenerator<String> {

    private Slugify slugger;

    public SlugGenerator() {
        slugger = MyBeansUtils.getBean(SlugifyImpl.class);
    }

    //...
}