π« Spring Beanis anobjectwhere itslifecycleis managed by theSpring IoC Container.
Spring Bean by its nature, is designed as a Singleton where there is only a single instance across the application, and the Spring IoC Container automatically handles the Spring Bean creation and relevant DI.
Spring Bean can be initialised by the following approaches:
π¨ Component Scan
@Component AnnotationβοΈ @Configuration & @Bean Annotations
@Configuration is @Component in depthποΈ XML
XML fileπ¨
Component Scanspecifically refers to the method where theSpring frameworkautomatically scans anyclassesorinterface(includingannotation interface),enum, orrecord, declared with@Component annotation.
@SpringBootApplication specifically runs the component scan over the specified path and its sub-paths, where by default, it scans the paths and its subpaths where the application file is located.
Below could be a good example of a Spring Component. Spring framework is responsible for managing the lifecycle of a ScanMe instance, and if necessary, BEAN_NAME could be further specified for better Spring Bean retrieval.
@Component
@Component(BEAN_NAME)
public class ScanMe {
}
Following that component scan is applied to annotation interfaces as well, automatic component scan also occurs to all annotations that implicitly include @Component annotation.
The most frequently used extended annotations are namely:
@Controller@Service@Repository@Configurationand as the names suggest, these annotations appear to have more well-understandable implications than they had been declared as @Component.
βοΈ
@Configurationcombined with@Beanis strictly an alternative to the conventionalBeanregistration approach withXML.
As mentioned above, @Configuration in depth functions upon @Component annotation where @Configuration is bound to the component scan.
Bean initialisation with @Configuration however, differs to the component scan as the earlier has to further provide @Bean annoated methods that instantiates, configures, and initialises a new object to be managed by the Spring IoC Container.
Underneath could be a good example of @Configuration with @Bean annotations:
AppConfig class
@Configuration
public class AppConfig {
@Bean
public MyServiceImpl myService() {
return new MyServiceImpl();
}
@Bean(BEAN_NAME)
public MyServiceImpl myService() {
return new MyServiceImpl();
}
@Bean
public A a() {
return new A(b);
}
@Bean
public B b() {
return new B();
}
}
BEAN_NAME specific to the Spring Bean object can be further specified, and registered Beans can be used for constructor DI, where often, following Dependency Inversion Principle combined with constructor DI, an instance of a concrete class has to be externally injected.
By default, the above configuration will be instantiated automatically by the Spring framework. Perhaps for testing purposes, SpringBean Container can be manually instantiated and its bean can be retrieved as below:
ApplicationContext
ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
MyService myServiceImpl = ac.getBean("myServiceImpl", MyServiceImpl.class);
ποΈ
XMLis alegacy styledapproach, where all thebeanspecification is provided within anXMLfile.
Underneath is a good example:
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
<!-- more bean definitions go here -->
</beans>
and the above metadata can be either configured automatically or manually (perhaps for testing) like below, where the file paths are provided to a constructor of ClassPathXmlApplicationContext class:
ApplicationContext
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");
π« In
Spring,bean proxyingis aninternal mechanismused by theSpring IoC Containerto apply theproxy pattern.
Instead of directly managing instances of the beans (i.e., the actual class instances), Spring injects proxy instances that represent these beans.
A Spring Bean Proxy is implemented via:
πΏ JDK Dynamic Proxy
beans implementing one or more interfaces.proxy instance implementing those interfaces.π CGLIB (Code Generation Library)
proxy creator for beans with no interfaces.subclass proxySpring manipulates the Java bytecode to create proxies, and the proxy mechanism allows Spring to intercept bean creation and execution by implementing certain additional behaviours such as transaction management, security checks, or lazy initialisation that could be strictly necessary for the Spring applications.
Spring AOP and Spring DI are good examples of Spring Bean Proxies where extra logics are further implemented behind the scenes.
Underneath could be a good practical example of bean proxying, in which given the Spring @Configuration, its instance is registered as a Spring Bean Proxy followed by $$SpringCGLIB$$0.
// Configuration
@Configuration
public class AppConfig {
@BEAN
public SPRING_BEAN SPRING_BEAN() {
return new SPRING_BEAN();
}
}
}
// test
@Test
void configurationDeep() {
ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
AppConfig bean = ac.getBean(AppConfig.class);
System.out.println("bean = " + bean.getClass());
// bean = class hello.core.AppConfig$$SpringCGLIB$$0
}
Spring applies a proxy pattern to intercept the instance creation and ultimately apply communal logics critical for Spring framework.
Assumably, following the Spring IoC Container's internal mechanism where it registers bean and returns a singleton instance for every Spring Bean calls, a proxy of the above config class could be illustrated as below:
@Configuration
public class AppConfig {
@BEAN
public SPRING_BEAN SPRING_BEAN() {
if (SPRING_BEAN is in Spring IoC Container) {
return SPRING_BEAN in Spring IoC Container;
} else { // NO SPRING_BEAN in Spring IoC Container
// instantiate SPRING_BEAN and register in Spring IoC Container
return SPRING_BEAN
}
}
}
and a proxy for specific Spring Bean may be as well altered to an original instance where the extra logics wrapping the original method invocation could be applied:
public class SPRING_BEAN_PROXY extends SPRING_BEAN {
@Override
public void sth() {
// BEFORE
RUN SOMETHING;
//
super.sth(); // SPRING_BEAN.sth();
// AFTER
RUN SOMETHING;
//
}
}
μ€νλ§ μ
λ¬Έμ μν μλ° κ°μ²΄ μ§ν₯μ μ리μ μ΄ν΄
μ€νλ§ ν΅μ¬ μ리 - κΈ°λ³ΈνΈ (κΉμν)
F-Lab