What is Spring IOC?
IOC : Inversion of control, Rather than creating and using dependent objects directly, inject an object.
Spring IOC container
BeanFactory
Center storage of application component
Read bean definitions from bean configuration source, configure and serve beans
Make configuration file like the picture below.
Bean
The object which manage from Spring IOC container
Benefit
Manage dependency
Scope
Life cycle interface
Configure using XML file and annotation.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" > <bean id ="bookService" -- > Enroll class to use bean class="com.example.demo.book.BookService" --> Write class path scope="singleton"> --> Write scope singleton or prototype and so on <property name ="bookRepository" ref ="bookRepository" /> </bean > <bean id ="bookRepository" class ="com.example.demo.book.BookRepository" /> </beans >
In application.xml, property that under the beans tag are taken from ‘setBookRepository’ in BookService
1 <property name ="bookRepository" ref ="bookRepository" />
1 2 3 4 5 6 7 8 9 @Service public class BookService { private BookRepository bookRepository; public void setBookRepository (BookRepository bookRepository) { this .bookRepository = bookRepository; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 public class Application { public static void main (String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("application.xml" ); String [] beanNames = context.getBeanDefinitionNames(); System.out.println(beanNames); BookService bookService = (BookService) context.getBean("bookService" ); System.out.println(bookService.bookRepository != null ); } }
The result is like below code.
1 2 3 4 [Ljava.lang.String;@2db7a79b true Process finished with exit code 0
But this way how to manage bean is inconvenient.
So Component-scan has appeared to solve the above method inconvenient.
1 2 3 4 5 6 7 8 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="com.example.demo"/> </beans>
component-scan can scan path within created base-package.
1 <context:component-scan base-package="com.example.demo"/>
Write annotation in class for component-scan.
For example, @component, @Controller, @Service, @Repository
1 2 3 4 5 6 7 8 9 10 11 12 13 @Component public class BookService { public BookRepository bookRepository; public void setBookRepository (BookRepository bookRepository) { this .bookRepository = bookRepository; } } @ Component public class BookRepository {}
But they can’t still dependency injection yet.
Write @Autowired or @inject for dependency injection.
1 2 3 4 5 6 7 8 9 @Service public class BookService { @Autowired public BookRepository bookRepository; public void setBookRepository (BookRepository bookRepository) { this .bookRepository = bookRepository; } }
So result is like below code and same above one.
1 2 [Ljava.lang.String;@56193c7d true
Many developer want write configure using java code, so can write this way instead XML file like below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Configuration public class ApplicationConfig { @Bean public BookService bookService () { BookService bookService = new BookService(); bookService.setBookRepository(bookRepository()); return bookService; } @Bean public BookRepository bookRepository () { return new BookRepository(); } }
Also Can inject in method paremeter
1 2 3 4 5 6 @Bean public BookService bookService (BookRepository bookRepository) { BookService bookService = new BookService(); bookService.setBookRepository(bookRepository); return bookService; }
Of course can use injection using @Autowired, then code like below.
1 2 3 4 5 6 7 8 9 @Bean public BookService bookService () { return new BookService(); } @Bean public BookRepository bookRepository () { return new BookRepository(); }
Also can use to way component-scan like this.
1 2 3 4 5 @Configuration @ComponentScan (basePackageClasses = Application.class ) public class ApplicationConfig {}
Now see the main method.
1 2 3 4 5 6 7 8 9 10 11 12 13 public class Application { public static void main (String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class ) ; String [] beanNames = context.getBeanDefinitionNames(); System.out.println(beanNames); BookService bookService = (BookService) context.getBean("bookService" ); System.out.println(bookService.getBookRepository() != null ); } }
Spring boot can create context if using @SpringBootApplication.
1 2 3 4 5 6 @SpringBootApplication public class Application { public static void main (String[] args) { } }