Spring foundation and IOC

Posted by crusty_php on Sat, 25 Dec 2021 20:52:39 +0100

1 Concept

Spring is an open source framework, which originated from a lightweight Java development framework rising in 2003. For a detailed overview, please refer to Baidu Encyclopedia

Spring is created to solve the complexity of enterprise application development. The core of spring is inversion of control (IOC) and aspect oriented (AOP). In short, spring is a layered lightweight open source framework

Reference to relevant documents

IOC : https://blog.csdn.net/ivan820819/article/details/79744797
Six principles of software design: http://www.uml.org.cn/sjms/201211023.asp#5
Low coupling: https://blog.csdn.net/ellis1970/article/details/84302912

2 advantages

  1. It is convenient to decouple and simplify development. Spring is a big factory, which can create all objects and maintain dependencies and hand them over to spring for management
  2. With the support of AOP programming, Spring provides aspect oriented programming, which can easily realize the functions of permission interception, operation monitoring and so on
  3. Declarative transaction support only needs to be configured to manage transactions without manual programming to facilitate program testing. Spring supports Junit4 and can easily test spring programs through annotations
  4. It is convenient to integrate various excellent frameworks. Spring does not exclude various excellent open source frameworks. It provides direct support for various excellent frameworks (such as Struts, Hibernate, MyBatis, Quartz, etc.)
  5. Reduce the difficulty of using Java EE APIs. Spring provides encapsulation for some APIs that are very difficult to use in Java EE development (JDBC, JavaMail, remote call, etc.), which greatly reduces the difficulty of applying these APIs

3 Spring Framework Runtime

The Core Container is the most basic package dependency we want to import using spring

4 create Spring project in IDEA

4.1 create a maven project

4.2 introducing package dependency of Spring

<properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <spring.version>5.2.5.RELEASE</spring.version>
    </properties>

    <dependencies>
        <!--Spring Core foundation dependency-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!--Log correlation-->
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <!--Test related-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <!--Automatic generation getter and setter-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
        </dependency>
    </dependencies>

4.3 add profile

The name of the configuration file can be set arbitrarily. It is recommended to set it to ApplicationContext XML, so here we create a file named applicationContext.xml in the resource directory XML configuration file

<?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">
</beans>

4.4 write corresponding code

Create the code of dao,model,service and other layers under the java of main

4.5 hand over Bean instantiation to Spring

In ApplicationContext Configure the following code in the beans tag in the XML configuration file

	<!--
    adopt spring Manage instances and dependencies
    name Dependent name
    class Specific dependence
    -->
<bean name="userDao" class="com.tledu.dao.impl.UserDaoImpl"/>
<bean name="userService" class="com.tledu.service.impl.UserServiceImpl">
    <!--
    Inject this property
    name Property name, according to set method
    ref: Refer to other dependencies, and refer to the above configuration userDao
    -->
    <property name="userDao" ref="userDao"/>
</bean>

4.6 testing

public class UserServiceTest {

    @Test
    public void add() {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(
                "applicationContext.xml");
        // userService is the id or name of the bean
        UserService userService = (UserService) applicationContext
                .getBean("userService");
        userService.add(null);
    }
}

5 injection mode

5.1 set method injection

<bean name="userDao" class="com.tledu.dao.impl.UserDaoImpl"/>
<bean name="userService" class="com.tledu.service.impl.UserServiceImpl">
	<property name="userDao" ref="userDao"/>
</bean>

5.1. 1 general attribute injection

<bean name="userDao" class="com.tledu.zrz.dao.impl.UserDaoImpl">
<!-- If not pointing to an object,Direct use value Just set the value -->
	<property name="daoId" value="82"></property>
	<property name="daoStatus" value="good"></property>
</bean>

5.1. 2 set attribute injection

<bean name="userDao" class="com.tledu.zrz.dao.impl.UserDaoImpl">
  <property name="lists" >
  	<list>
    	<value>1</value>
    	<value>2</value>
  	</list>
  </property>
  <property name="sets" >
  <!-- set Non repeatable,Repeat without adding,So there's only the first three -->
  	<set>
    	<value>3</value>
    	<value>3</value>
    	<value>5</value>
    	<value>4</value>
  	</set>
  </property>
  <property name="maps">
  <!-- mapkey Non repeatable,repeat key Do not add,value cover -->
  	<map>
    	<entry key="1"  value="2"></entry>
    	<entry key="1"  value="3"></entry>
    	<entry key="2"  value="2"></entry>
  	</map>
  </property>
	</bean>

	<bean id="userService" class="com.tledu.zrz.service.UserService"
  scope="singleton">
  <!-- Construction method injection -->
  <constructor-arg>
  	<ref bean="userDao" />
  </constructor-arg>
	</bean>

Related variables are defined in related classes and must have setter methods

5.2 construction method

 <bean name="userDao" class="com.tledu.spring.dao.impl.UserDaoImpl" />
    <bean id="userService" class="com.tledu.spring.service.UserService">
        <constructor-arg ref="userDao"/>
    </bean>

5.3 note injection

Mentioned later

6 Scope properties

In spring, scope is the life cycle of an object in the spring container (IOC container), which can also be understood as the creation method of an object in the spring container

At present, there are five values for scope:
Before Spring 2.0, there were singleton and prototype;
After Spring 2.0, in order to support the ApplicationContext of web applications, three other request, session and global session types are enhanced (these three types will not be explained later and will be mentioned later)

6.1 Singleton

This value indicates that there is only one instance when it is created in the container, and all references to this bean are single instances.
That is, the creation object is in singleton mode, and if it is not set, singleton will be used by default

6.2 Prototype

When the spring container outputs the bean object of prototype, it will regenerate a new object to the requester every time. Every time the container returns a new instance of the object to the requester, the object will "live and die by itself". The most typical embodiment is that when spring is integrated with struts 2, the scope of action should be changed to prototype

Simply put, a new object is created every time it is acquired, and the life cycle of this object is not managed by Spring

7 automatic assembly (Autowire)

There is no need to specify the injection method

7.1 byName

byName matches the name of the setter method. If it cannot be found, it will not be assigned
For example, the setUserDao method will find UserDao. If the bean ID is UserDao, it cannot be found. It is case sensitive

<bean name="userDao" class="com.tledu.zrz.dao.impl.UserDaoImpl">
	</bean>
	<bean id="userService" class="com.tledu.zrz.service.UserService"  
  autowire="byName">
</bean>

7.2 byType

byType is matched according to the data type in the parameter list of the setter method, if beans If multiple objects of the same type appear in XML, an error will be reported
For example, the setUserDao(UserDao userDao) method will find UserDao. If it is an interface, it will find the corresponding implementation class object

<bean name="userDao" class="com.tledu.zrz.dao.impl.UserDaoImpl">
	</bean>
	<bean id="userService" class="com.tledu.zrz.service.UserService"  
  autowire="byType">
</bean>

7.3 constructor

Dependency injection can be performed according to the constructor.

7.4 precautions

Using automatic assembly requires a public parameterless construction. Although the object can still be created even if it is a private construction method, it is better to provide a public one in case other frameworks need it

8 life cycle and delayed loading

8.1 life cycle

8.1. 1 Concept

Previous servlet life cycle
Construction method – init – service – destroy

There are no init, service and destroy in Spring, but we can specify a method to execute after the object is created and a method to execute when it is finally destroyed

8.1. 2 implementation

Create related methods

public void init(){
  System.out.println("init--------");
	}
	public void destroy(){
  System.out.println("destroy----------");
	}
	public UserService() {
  System.out.println("service Construction method");
}

configuration file

<bean name="userDao" class="com.tledu.zrz.dao.impl.UserDaoImpl" >
	</bean>
	<!--  
  init-method : Method for setting initialization
  destory-method : Used to set the method for destroying resources
  -->
	<bean id="userService" class="com.tledu.zrz.service.UserService"  
  autowire="byName"   init-method="init" destroy-method="destroy"  >
	</bean>

8.1. 3 attention

Destroy executes because we create objects in singleton mode by default

At this time, the object life cycle will be bound with the Spring container life cycle, so when we destroy the Spring container, we will destroy all objects and automatically call the destroy method

However, if we set the scope to prototype, the life cycle of the object will not be bound to the Spring container, and the destroy method of the object will not be executed when the Spring container is destroyed

When the scope is of prototype type, our container is only responsible for the creation of instances, and the caller is responsible for the life cycle after creation

8.2 delayed loading

The Spring container is executing by default
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
Create an object and call init when parsing

If we don't want a class to create objects when parsing, but when using, we need to set late loading

8.2. 1 implementation

Create related methods

public UserDaoImpl(){
  System.out.println("Dao Construction method");
}
public UserService() {
  System.out.println("service Construction method");
}

configuration file

<bean name="userDao" class="com.tledu.zrz.dao.impl.UserDaoImpl" >
<bean id="userService" class="com.tledu.zrz.service.UserService"  scope="prototype"
  	autowire="byName"   init-method="init" destroy-method="destroy" lazy-init="true"  >
</bean>

It can be seen from the results that the UserService object is not created and will only be created when we use this object

We can add default lazy init = "true" in the beans tag to load all beans late

9 IOC notes

There are two configuration methods in the Spring framework: annotation and XML, including IOC and AOP in Spring. There are two methods: XML and annotation. The two annotations have their own advantages and disadvantages, but they are used more in the framework

9.1 annotation injection implementation

9.1. 1. Introduce dependency

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-aop</artifactId>
	<version>${spring.version}</version>
</dependency>

9.1. 2. Enable annotation support

The first method: open in the configuration file

<?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
       http://www.springframework.org/schema/context/spring-context.xsd">
	<!-- Introducing annotation constraints -->
	<!-- Automatic assembly using annotation form -->
	<context:annotation-config />
</beans>

The second method: open in the configuration class

//Adding Configuration indicates that this is an annotation Configuration class
@Configuration
@ComponentScan(basePackages = "com.tledu.spring3")
public class SpringConfig {
    @Bean
    public Connection getConnection(JdbcProperties jdbcProperties) throws SQLException, ClassNotFoundException {
        Class.forName(jdbcProperties.getDriver());
        return DriverManager.getConnection(jdbcProperties.getUrl(), jdbcProperties.getUsername(), jdbcProperties.getPassword());
    }
}
Bean

Function: this annotation can only be written on the method, indicating that an object is created using this method and put into the spring container.
Attribute: Name: specify a name (i.e. bean id) for the object created by the current @ bean annotation method

PropertySource

Function: used for loading The configuration in the properties file. For example, when we configure the data source, we can write the information of connecting to the database into the properties configuration file, and we can use this annotation to specify the location of the properties configuration file.
Property: value []: used to specify the location of the properties file. If it is under the classpath, you need to write classpath

@Component
@PropertySource("classpath:jdbc.properties")
public class JdbcProperties {
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;
    @Value("10")
    private Integer max;
}
Import

Function: used to import other Configuration classes. When importing other Configuration classes, you can no longer write @ Configuration annotation. Of course, there's no problem writing it.
Attribute: value []: used to specify bytecode of other configuration classes.

9.1. 3. Use annotations in business class

Add @ Component to all classes that need to instantiate objects
The default is to store the class name in lowercase
You can use @ Component("xxx") or @ Component(value = "xxx") to set the name

@Component
public class UserService {
    private IUserDao userDao;

    @Autowired
    public void setUserDao(IUserDao userDao) {
        this.userDao = userDao;
    }
}

Autowired annotation

This annotation can be added to the set method or directly loaded attributes. If it is written on the setter method, it will be injected through the setter method. If it is written on a variable, it will directly set the value of the variable through reflection without going through the setter method.
During injection, an instantiated object matching the attribute data type will be found in the spring container and injected. byType is used by default and matched according to the type.
If only one object of this data type can be found, the object will be injected directly.
If multiple objects of the same type are found, they will be automatically changed to byName for matching according to the local variable name of the parameter list corresponding to the set method.

And @ Qualifier: can match with the specified name

9.1. 4 configure scanning

The first method: configure in the configuration file

	<!-- Automatic assembly using annotation form -->
	<context:annotation-config />
	<!-- Instantiate objects using annotations -->
	<context:component-scan base-package="com.tledu.spring3" />
</beans>

The second method: configure in the configuration class

//Configure package scanning
@ComponentScan(basePackages = "com.tledu.spring3")
public class SpringConfig {

9.2 annotation classification and meaning

@Controller: the web layer is the class that interacts with the page

@Service: business layer, mainly processing logic

@Repository: persistence layer, that is, Dao operates the database

These three annotations are to make the use of the annotation class itself clear, and Spring will enhance it in subsequent versions

@Component: the most common component, which can be injected into the spring container for management

@Value: used to inject common types It can be written on variables and setter methods

@Autowired: automatic assembly. The above description is more detailed. You can refer to the above

@Qualifier: force name injection

@Resource is equivalent to: @ Autowired and @ Qualifier are used together

@Scope: sets the lifecycle of an object in the spring container
Value:

singleton: single case
prototype: multiple cases

@PostConstruct: equivalent to init method

@PreDestroy: equivalent to destroy method

Topics: Java Spring SSM