13

I have my repository interface as

import org.springframework.data.jpa.repository.JpaRepository;

import org.springframework.stereotype.Repository;


@Repository
public interface MyRepository extends JpaRepository<Tokens, Long>{
}

and the service impl file in where I want to use above repository is not a @Component or @Service because its object is created using new. So it is not allowing autowiring or injecting the repository in my service impl class.

Is there any other way around to implement in such case?

Draken
  • 3,134
  • 13
  • 34
  • 54
Navdeep Singh
  • 151
  • 1
  • 2
  • 7
  • 2
    Why did you use new instead of autowiring in the object which needs access to the repository? – Draken Jul 30 '18 at 13:59
  • Shouldn't you be able to use a JNDI lookup to get a managed instance of the `MyRepository`? I did that with EE beans in Pojos, but I never tried it within Spring. But I would assume, there is no difference in doing so. – Korashen Jul 30 '18 at 14:00
  • Pass in the application context to the constructor of the `new` class. Then you can pull the `Repository` from the context, using `.getBean` method. – Dan Jul 30 '18 at 14:03
  • 2
    You might be able to get the `Repository` instance by getting it from the application context using one of the static methods. Refer to this here: https://stackoverflow.com/questions/129207/getting-spring-application-context However, why don't you have your service properly managed by Spring? you can have a wrapper object to do that, if the code using `new` is not yours or difficult to refactor. If you don't use the framework as intended it will work against you instead of giving you its dependency injection advantages. – jbx Jul 30 '18 at 14:05
  • I think there's a better way of doing this rather than instantiating a new Service. Why can't you autowire this Service? – Dan Jul 30 '18 at 14:06
  • I am creating serviceimpl() object using new because this is a sdk and developers using this sdk can instantiate service impl using new as well. So I just want to handle both the cases (autowired and new). – Navdeep Singh Jul 30 '18 at 14:12
  • going from using "new" to going via JNDI - that escalated quickly – Toby Sep 26 '21 at 19:43

1 Answers1

3

There are a couple of options available.

First of all, you can use it as a normal dependency and use a factory bean to instantiate your object.

@Component
public class MyFactoryBean {

    private Repository repository;

    @Autowired
    public MyFactoryBean(Repository repository) {
        this.repository = repository;
    }

    public Instance getInstance(Parameter parameter) {
        return new Instance(repository, parameter);
    }
}

If your parameter does not change at runtime, you can provide a bean in your configuration:

@Configuration
public class MyConfiguration {

    private Repository repository;

    @Autowired
    public MyConfiguration(Repository repository) {
        this.repository = repository;
    }

    @Bean 
    public Instance instance(){
        Parameter parameter = ... // value in a config file or static value 
        return new Instance(repository, parameter);
    }
}

Also, you can use the AutowireCapableBeanFactory to inject dependencies as normal for objects not managed by Spring. Remember that you need to use setter injection tough.

private AutowireCapableBeanFactory beanFactory;

@Autowired
public MyFactoryBean(AutowireCapableBeanFactory beanFactory) {
    this.beanFactory = beanFactory;
}

public void doStuff() {
    MyService service = new MyService();
    beanFactory.autowireBean(service); // dependencies will be autowired
}
Glains
  • 2,773
  • 3
  • 16
  • 30