Topics covered in this page:
A) Spring Inversion of Control (IOC)
B) Dependency injection
C) XML Configuration using p-namespace
D) Autowiring Dependencies
E) Lazy Initialization
A) Spring Inversion of Control (IOC) - Transfers the control of objects to a container or framework
Example: ApplicationContext
package com.sample.Spring;
public class MessagePojo {
private String message;
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
}
package com.sample.Spring;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyMainClass {
public static void main(String[] args) {
ApplicationContext appContext = new ClassPathXmlApplicationContext("mybean.xml");
MessagePojo pojo = (MessagePojo) appContext.getBean("messageBean");
System.out.println(pojo.getMessage());
}
}
xml file under /src/main/resources
<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-3.0.xsd">
<bean id="messageBean" class="com.sample.Spring.MessagePojo">
<property name="message" value="This is predefined value in xml"></property>
</bean>
</beans>
B) Dependency injection: A pattern we can use to implement IoC
1) Constructor-Based Dependency Injection
1) Constructor-Based Dependency Injection
2) Setter-Based Dependency Injection
3) Field-Based Dependency Injection
1) Constructor-Based Dependency Injection
package com.sample.Spring;
public class SpellChecker {
public SpellChecker() { System.out.println("Inside SpellChecker constructor."); }
public void checkSpelling() { System.out.println("Inside checkSpelling method."); }
}
package com.sample.Spring;
public class TextEditor {
private SpellChecker spellChecker;
public TextEditor(SpellChecker spellChecker) {
System.out.println("Inside TextEditor constructor.");
this.spellChecker = spellChecker;
}
public void spellCheck() { spellChecker.checkSpelling(); }
}
package com.sample.Spring;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("mybean.xml");
TextEditor te = (TextEditor) context.getBean("textEditor");
te.spellCheck();
}
}
<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-3.0.xsd">
<bean id = "textEditor" class = "com.sample.Spring.TextEditor">
<constructor-arg ref = "spellChecker"/>
</bean>
<bean id = "spellChecker" class = "com.sample.Spring.SpellChecker"></bean>
</beans>
public class SpellChecker {
public SpellChecker() { System.out.println("Inside SpellChecker constructor."); }
public void checkSpelling() { System.out.println("Inside checkSpelling method."); }
}
package com.sample.Spring;
public class TextEditor {
private SpellChecker spellChecker;
public TextEditor(SpellChecker spellChecker) {
System.out.println("Inside TextEditor constructor.");
this.spellChecker = spellChecker;
}
public void spellCheck() { spellChecker.checkSpelling(); }
}
package com.sample.Spring;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("mybean.xml");
TextEditor te = (TextEditor) context.getBean("textEditor");
te.spellCheck();
}
}
<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-3.0.xsd">
<bean id = "textEditor" class = "com.sample.Spring.TextEditor">
<constructor-arg ref = "spellChecker"/>
</bean>
<bean id = "spellChecker" class = "com.sample.Spring.SpellChecker"></bean>
</beans>
Output:
Inside SpellChecker constructor. Inside TextEditor constructor. Inside checkSpelling.
2) Setter-Based Dependency Injection
package com.sample.Spring;
public class TextEditor {
private SpellChecker spellChecker;
// Setter
public void setSpellChecker(SpellChecker spellChecker) {
System.out.println("Inside setSpellChecker.");
this.spellChecker = spellChecker;
}
System.out.println("Inside setSpellChecker.");
this.spellChecker = spellChecker;
}
// Getter
public SpellChecker getSpellChecker() {
return spellChecker;
}
public void spellCheck() {
spellChecker.checkSpelling();
}
}
public SpellChecker getSpellChecker() {
return spellChecker;
}
public void spellCheck() {
spellChecker.checkSpelling();
}
}
<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-3.0.xsd">
<bean id = "textEditor" class = "com.sample.Spring.TextEditor">
<property name = "spellChecker" ref = "spellChecker"/>
</bean>
<bean id = "spellChecker" class = "com.sample.Spring.SpellChecker"></bean>
</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-3.0.xsd">
<bean id = "textEditor" class = "com.sample.Spring.TextEditor">
<property name = "spellChecker" ref = "spellChecker"/>
</bean>
<bean id = "spellChecker" class = "com.sample.Spring.SpellChecker"></bean>
</beans>
Output:
Inside SpellChecker constructor. Inside setSpellChecker. Inside checkSpelling.
3) Field-Based Dependency Injection
package com.sample.Spring;
public class OrderService {
public String getOrderDetails(String orderId) {
return "Order details for order id=" + orderId;
}
}
package com.sample.Spring;
import org.springframework.beans.factory.annotation.Autowired;
public class OrderServiceClient {
@Autowired
private OrderService orderService;
public void showPendingOrderDetails() {
System.out.println(orderService.getOrderDetails("300"));
}
}
package com.sample.Spring;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MainApp {
@Bean
public OrderService orderService() {
return new OrderService();
}
@Bean
public OrderServiceClient orderServiceClient() {
return new OrderServiceClient();
}
public static void main(String... strings) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainApp.class);
OrderServiceClient bean = context.getBean(OrderServiceClient.class);
bean.showPendingOrderDetails();
}
}
Output:
Order details for order id=300
C) XML Configuration using p-namespace
THIS
<?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-3.0.xsd">
<bean id = "john-classic" class = "com.example.Person">
<property name = "name" value = "John Doe"/>
<property name = "spouse" ref = "jane"/>
</bean>
<?xml version = "1.0" encoding = "UTF-8"?>
CAN BE REPLACED BY THIS
<beans xmlns = "http://www.springframework.org/schema/beans"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xmlns:p = "http://www.springframework.org/schema/p"
xsi:schemaLocation = "http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id = "john-classic" class = "com.example.Person"
p:name = "John Doe"
p:spouse-ref = "jane"/>
</bean>
</beans>
D) Autowiring Dependencies
1) The Spring framework enables automatic dependency injection. In other words, by declaring all the bean dependencies in a Spring configuration file, Spring container can autowire relationships between collaborating beans. This is called Spring bean autowiring.
2) When a bean is being constructed, the @Autowired dependencies should be available. Otherwise, if Spring cannot resolve a bean for wiring, it will throw an exception. To fix this, we need to declare a bean of the required type: @Autowired(required = false)
3) We can use @Autowired on Properties, Setters and Constructors
4) By default, Spring resolves @Autowired entries by type. If more than one bean of the same type is available in the container, the framework will throw a fatal exception. To resolve this conflict, we need to tell Spring explicitly which bean we want to inject using @Qualifier annotation
@Component("fooFormatter")
public class FooFormatter implements Formatter {
public String format() {
return "foo";
}
}
@Component("barFormatter")
public class BarFormatter implements Formatter {
public String format() {
return "bar";
}
}
public class FooService {
@Autowired
@Qualifier("fooFormatter")
private Formatter formatter;
}
5) Autowiring can be done by Custom Qualifier
@Qualifier
@Target({
ElementType.FIELD, ElementType.METHOD, ElementType.TYPE, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface FormatterType {
String value();
}
@FormatterType("Foo")
@Component
public class FooFormatter implements Formatter {
public String format() {
return "foo";
}
}
@FormatterType("Bar")
@Component
public class BarFormatter implements Formatter {
public String format() {
return "bar";
}
}
@Component
public class FooService {
@Autowired
@FormatterType("Foo")
private Formatter formatter;
}
E) Lazy Initialization
When we configure a bean with lazy initialization, the bean will only be created, and its dependencies injected, once they're needed.
Enable Lazy Initialization: It can be enabled in any of the below following ways
1) In application.yml add
spring:
main:
lazy-initialization: true
Note: All the defined beans will use lazy initialization, except for those that we explicitly configure with @Lazy(false).
2) In application.properties add
spring.main.lazy-initialization=true
Note: All the defined beans will use lazy initialization, except for those that we explicitly configure with @Lazy(false).
3) Use the SpringApplicationBuilder method
SpringApplicationBuilder(Application.class)
.lazyInitialization(true)
.build(args)
.run();
4) Use the SpringApplication class
SpringApplication app = new SpringApplication(Application.class);
app.setLazyInitialization(true);
app.run(args);
5) Use with Example
public class Writer {
private final String writerId;
public Writer(String writerId) {
this.writerId = writerId;
System.out.println(writerId + " initialized!!!");
}
public void write(String message) {
System.out.println(writerId + ": " + message);
}
}
@SpringBootApplication
public class Application {
@Bean("writer1")
public Writer getWriter1() {
return new Writer("Writer 1");
}
@Bean("writer2")
public Writer getWriter2() {
return new Writer("Writer 2");
}
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(Application.class, args);
ctx.setLazyInitialization(true);
ctx.run(args);
System.out.println("Application context initialized!!!");
Writer writer1 = ctx.getBean("writer1", Writer.class);
writer1.write("First message");
Writer writer2 = ctx.getBean("writer2", Writer.class);
writer2.write("Second message");
}
}
No comments:
Post a Comment