1

I know that there are questions similar to this one, but none of them have helped me. I'm following along this tutorial, and the part I can't wrap my mind around is:

@SpringBootApplication
public class Application {

    private static final Logger log = 
    LoggerFactory.getLogger(Application.class);

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

    @Bean
    public CommandLineRunner demo(CustomerRepository repository) {
        return (args) -> {
            // save a couple of customers
            ...
            // more lines, etc...

What I don't understand is where the repository passed into demo comes from. I know that the Autowired annotation can do something like that, but it isn't used at all here.

The more specific reason I ask is because I'm trying to adapt what they do here to an application I'm working on. I have a class, separate from all of the persistence/repository stuff, and I want to call repository methods like save and findAll. The issue is that the repository is an interface, so I can't instantiate an object of it to call the methods. So do I have to make a new class that implements the interface and create an object of that? Or is there an easier way using annotations?

Calvin Godfrey
  • 2,171
  • 1
  • 11
  • 27
  • all those defaults methods like save and findAll are created by spring using reflection. If you want to overwrite implementing a class – g__n Jan 15 '19 at 17:36
  • 2
    the a look in the `SimpleJpaRepository` class, it is implementing your methods – g__n Jan 15 '19 at 17:37
  • Thanks @g_n, I'll look into that. – Calvin Godfrey Jan 15 '19 at 17:41
  • If your application is a SpringBoot application, it is enough to declare a JPA repository interface , and Spring will instantiate a class which implements the interface. If you want to access it from a class that is not a bean, you can send your class the interface from a class that is a bean and can use @Autowired or from some place whrere you can do ApplicationContext.getBean( <>.class ) – Gonen I Jan 15 '19 at 17:56

3 Answers3

1

When creating a @Bean, adding the repository in the parameters of the bean is enough to wire the repos in your bean. This works pretty much like adding @Autowired annotation inside a class that is annotated as @Component or something similar.

Spring works mostly with interface, since that is simplier to wire vs wiring concrete classes.

sweet suman
  • 1,031
  • 8
  • 18
  • The issue is that the class I'm trying to use these methods from is not a `Bean`. It's completely separate from Spring Framework. – Calvin Godfrey Jan 15 '19 at 17:39
  • See my answer above and register a bean that will invoke your functionality and annotate the method accordingly. – h.alex Jan 15 '19 at 17:47
  • 1
    'The issue is that the class I'm trying to use these methods from is not a Bean' - then make it one! You can literally just write `@Bean public MyClass myClass(CustomerRepository repository) {return new MyClass(customerRepository); }` and then change the `CommandLineRunner` bean definition to `@Bean public CommandLineRunner demo(MyClass myClass) {...}`, right in the `Application` class – crizzis Jan 15 '19 at 22:49
0

Can you try @Repository before the declaration of class? Worked for me in a Spring MVC structure.

@Repository
public class EntityDAOImpl implements EntityDAO{
...
}
Groot
  • 211
  • 1
  • 5
  • 11
0

The thing to wrap your head around is a Spring Boot application at startup time aims to resolve its dependancy tree. This means discovering and instantiating Beans that the application defines, and those are classes annotated with @Service, @Repository, etc.

This means the default constructor (or the one marked with @Autowire) of all beans is invoked, and after all beans have been constructed the application starts to run.

Where the @Bean annotation comes into play is if you have a bean which does not know the values of it's constructor parameters at compile time (e.g. if you want to wire in a "started at" timestamp): then you would define a class with an @Configuration annotation on it, and expose an @Bean method in it, which would return your bean and have parameters that are the beans dependencies. In it you would invoke the beans constructor and return the bean.

Now, if you want a certain method of some class to be invoked after the application is resolved, you can implement the CommandLineRunner interface, or you can annotate a method with @PostConstruct.

Some useful links / references:

  1. https://docs.spring.io/spring-javaconfig/docs/1.0.0.m3/reference/html/creating-bean-definitions.html

  2. https://www.baeldung.com/spring-inject-prototype-bean-into-singleton

  3. Running code after Spring Boot starts
  4. Execute method on startup in Spring
h.alex
  • 902
  • 1
  • 8
  • 31