1,IOC
Inverse of Control – IOC, control reversal, reversing the control of the object to Spring!
Using IOC can solve the problem of high coupling of programs
Control reversal
Suppose I need a function. In this function, I need to call the service layer, and then call the dao layer to get the data. Traditional Java EE development directly creates a new service and then a new dao. In spring, the new process is handed over to the spring framework. It means that I give the right to create resources to the spring framework, which is called control inversion.
decoupling
Just now we said that the creation of resources was entrusted to spring, so I can find it whenever I need it. This process is like engineering mode. But in the spring framework, which objects it needs to create, it needs a configuration file. This configuration file tells spring which resources need to be created.
eg: suppose I need to go to the database to query the data display page
When the program starts, the spring framework looks for the configuration file to create resources, places the resources in a container, starts running, front-end data requests, looks for the controller layer in spring, then looks for the service layer, and then looks for the dao layer for data. Finally, the data is returned to the controller and displayed on the page. The service is injected into the controller layer by spring, and the dao layer is injected into the service layer by spring. The division of labor in this process is clear, and each layer performs its own duties. In a traditional development, new is directly in the servlet, then the data is checked, and then the data is returned to the interface. In case of operating more than one judgment and querying different tables, the code of this servlet becomes very bloated. Not to mention the slow development, it's hard for you to read the code after development. So control inversion can be used to decouple.
0. Configure spring with xml
<?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" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <bean id="student" class="com.tian.bean.pojo.Student"> <property name="name" value="zhangsan"></property> </bean> </beans>
1. Load the IOC container as a companion file
After creating a Configuration class and adding it to @ Configuration, the class becomes a Configuration class and is put into the Bean container
package com.tian.bean.config; import org.springframework.context.annotation.Configuration; // The configuration file annotation tells spring that this is a configuration class @Configuration public class MyConfig { }
However, the methods in this class will not be directly put into the IOC container. You need to use the @ Bean annotation method to put them into the IOC container
package com.tian.bean.config; import org.springframework.context.annotation.Configuration; // The configuration file annotation tells spring that this is a configuration class @Configuration public class MyConfig { @Bean(name = {"student1"}) public Student student(){ return new Student("Zhang San", 19); } }
According to the above code, the method student annotated by @ Bean can be put into the IOC container. The method name is the id of the method in the container. If you want to change an id for the method, you can click the source code of @ Bean, and we can see it
package org.springframework.context.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.beans.factory.annotation.Autowire; import org.springframework.beans.factory.support.AbstractBeanDefinition; @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Bean { /** * The name of this bean, or if plural, aliases for this bean. If left unspecified * the name of the bean is the name of the annotated method. If specified, the method * name is ignored. */ String[] name() default {}; }
The name attribute of the Bean container receives a string array, so you can use @ Bean(name = {"student1"}) to modify the id of the original method when returning to the source code
The IOC container defaults to the singleton mode. After the IOC container is created, the object of the instance has been put into the container, so every time we take the object out of the container is an object.
package com.tian.bean.test; import com.tian.bean.config.MyConfig; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import java.util.Arrays; public class MyConfigTest1DomeTest { public static void main(String[] args) { AnnotationConfigApplicationContext appc = new AnnotationConfigApplicationContext(MyConfig.class); Arrays.stream(appc.getBeanDefinitionNames()).sequential().forEach(System.out::println); Object student1 = appc.getBean("student"); Object student2 = appc.getBean("student"); System.out.println(student1 == student2); } }
>>> true
However, if @ Scope("prototype") is added to the method, the method will become a multi instance mode, and the same object of getBean() in the container will be different every time.
Execution sequence: since the singleton mode is created only once, all objects in the singleton mode will be put into the container after the IOC container is created, while those in the multi instance mode will be called only when used.
Conditional judgment
package com.tian.bean.conditional; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; public class ConditionalLinux implements Condition { /** * ConditionContext: Determine the context in which the condition can be used * AnnotatedTypeMetadata: Annotation information */ @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { // Get bean factory ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); // Get class loader ClassLoader classLoader = context.getClassLoader(); // Determine whether it is a windows system String property = context.getEnvironment().getProperty("os.name"); // Get the registration class defined by the bean BeanDefinitionRegistry registry = context.getRegistry(); if ("Linux".equals(property)) { return true; } return false; } }
package com.tian.bean.conditional; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; public class ConditionalWindows implements Condition { /** * ConditionContext: Determine the context in which the condition can be used * AnnotatedTypeMetadata: Annotation information */ @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { // Get bean factory ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); // Get class loader ClassLoader classLoader = context.getClassLoader(); // Determine whether it is a windows system String property = context.getEnvironment().getProperty("os.name"); // Get the registration class defined by the bean BeanDefinitionRegistry registry = context.getRegistry(); if ("Windows 8.1".equals(property)) { return true; } return false; } }
package com.tian.bean.test; import com.tian.bean.config.ConditionalTest; import com.tian.bean.pojo.ConditionalPojo; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.core.env.ConfigurableEnvironment; import java.util.Arrays; import java.util.Map; public class ConditionalPojoTest { public static void main(String[] args) { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ConditionalTest.class); // Gets the value of the environment variable ConfigurableEnvironment environment = applicationContext.getEnvironment(); System.out.println(environment.getProperty("os.name")); // Get the contents of the bean object Map<String, ConditionalPojo> beansOfType = applicationContext.getBeansOfType(ConditionalPojo.class); System.out.println(beansOfType); // View the objects in the bean container according to the type of class String[] beanNamesForType = applicationContext.getBeanNamesForType(ConditionalPojo.class); Arrays.stream(beanNamesForType).sequential().forEach(System.out::println); } }
@Import (class name. class)
Quickly import a component into the container
Use FactoryBean()
Summary:
If and add classes to the Bean container
/** * To register a component in a container: * 1,Package scanning + annotation (@ Controller,@Service,@Component) other customized need to use @ Component annotation * 2,@Bean[name={""}] * 3,@Import(Class name class) * - @Import() * - @ImportSelector:Import the selector and return an array of strings * - @ImportBeanDefinitionRegistrar: * 4,Use factorybean (project Bean) provided by Spring * - The factory Bean obtains the returned object by default * - To get the factory itself, you need to add a & representation to it */
2. Bean lifecycle
The process from Bean creation to initialization to destruction. The Bean life cycle is managed by the container.
1. Specify initialization and destruction methods
Init method and destruction method
2. Use annotations to specify lifecycle initialization and destruction methods
@Bean(initMethod = "init",destroyMethod = "detory") public Test test() { return new Test(); }
Initialization: call after the object is created and assigned
Destroy: when the container is about to close, single instance beans will be destroyed, but multi instance beans will not be destroyed
3. Let the Bean implement the InitializingBean and DisposableBean interfaces, and define initialization and destruction
package com.tian.bean.pojo; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.stereotype.Component; @Component public class Cat implements InitializingBean, DisposableBean { @Override public void destroy() throws Exception { System.out.println("cat Destroy"); } @Override public void afterPropertiesSet() throws Exception { System.out.println("cat establish"); } }
4. The initialization and destruction methods are defined using PostConstruct and PreDestory defined in the JSR250 specification
package com.tian.bean.pojo; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; public class Dog { public Dog() { System.out.println("Dog Nonparametric structure"); } // After the object is created and assigned, it is called. @PostConstruct public void init() { System.out.println("init Method called"); } @PreDestroy public void destory() { System.out.println("destory Method called"); } }
5. BeanPostProcessor is the processing operation before and after Bean initialization
- postProcessBeforeInitialization
- postProcessAfterInitialization
package com.tian.bean.pojo; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; public class Car implements BeanPostProcessor { public Car() { System.out.println("------Car Nonparametric structure-----"); } /** * Called before initialization */ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("postProcessBeforeInitialization call"); return bean; } /** * Called after initialization */ @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("postProcessAfterInitialization Called"); return bean; } }