spring framework - annotation application of IOC

Keywords: Spring Framework

Annotation application of spring IOC

To use annotation injection, you need to define a scan package

In previous projects, we all assigned beans or some attributes through xml files. In fact, there is another way of annotation. Many of them are used in enterprise development. Adding annotations to beans can quickly register beans to ioc container.

1. Register the bean into the IOC container using annotations

applicationContext.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"
       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">

    <!--
    If you want to customize bean Object added to IOC In the container, you need to add some annotations on the class
    Spring There are 4 main components to add notes:
    @Controller:Controller, recommended for controller Add this annotation to the layer
    @Service:Business logic. It is recommended to add this annotation to the business logic layer
    @Repository:For warehouse management, it is recommended to add this annotation to the data access layer
    @Component:Add this annotation to components that do not belong to the above base layer
    Note: Although we artificially add different annotations to different layers, in spring It seems that you can add any annotation at any layer
           spring The bottom layer will not give specific level verification annotations. The purpose of this writing is only to improve readability. It is the laziest way
           Is to give it to everyone who wants it IOC Container managed bean Object addition component annotation

    Using annotations requires the following steps:
    1,Add any of the above four annotations
    2,Add a component that automatically scans annotations. This operation requires dependencies context Namespace
    3,Add automatically scanned labels context:component-scan

	Note: when registering components with annotations, it is the same as registering components with configuration files, but note:
		1,Component id By default, the first character of the class name of the component is lowercase. If you need to change the name, you can add it directly in the annotation
		2,Components are singleton by default,If you need to configure the multi instance mode, you can add it under the annotation@Scope annotation
    -->
    <!--
    Define the base package for automatic scanning:
    base-package:Specify the base package to scan, spring At startup, all annotated classes under the basic package and sub package will be automatically
                Scan in IOC container
    -->
    <context:component-scan base-package="com.mashibing"></context:component-scan>
</beans>

PersonController.java

package com.mashibing.controller;

import org.springframework.stereotype.Controller;

@Controller
public class PersonController {
    public PersonController() {
        System.out.println("create object");
    }
}

PersonService.java

package com.mashibing.service;

import org.springframework.stereotype.Service;

@Service
public class PersonService {
}

PersonDao.java

package com.mashibing.dao;

import org.springframework.stereotype.Repository;

@Repository("personDao")
@Scope(value="prototype")
public class PersonDao {
}

2. Define classes to include and classes not to include when scanning packages

After the basic scanning package is defined, it may be necessary to selectively configure whether to register bean s into the IOC container in some cases. At this time, it can be configured in the following ways.

applicationContext.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"
       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">
    <context:component-scan base-package="com.mashibing" use-default-filters="false">
        <!--
        After defining the package for basic scanning, you can exclude some classes in the package and use the following methods:
        type:Represents the rule for the specified filter
            annotation: Exclude according to the annotation. Components marked with the specified annotation are not allowed,expression Indicates the annotation to filter
            assignable: Specifies that a specific class is excluded according to the class, expression Represents a specific class name that is not registered
            aspectj: Later aop Explain what to use when aspectj Expression, No
            custom: Define a typeFilter,Write your own code to determine which classes are filtered out, No
            regex: Use regular expression filtering without
        -->
<!--        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>-->

        <!--Specify which components are scanned only. By default, all components are scanned. Therefore, to configure at this time, you need to component-scan Add to label use-default-filters="false"-->
        <context:include-filter type="assignable" expression="com.mashibing.service.PersonService"/>
    </context:component-scan>
</beans>

3. Auto injection using @ AutoWired

The @ AutoWired annotation is required to realize automatic injection by using annotation.

PersonController.java

package com.mashibing.controller;

import com.mashibing.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class PersonController {

    @Autowired
    private PersonService personService;

    public PersonController() {
        System.out.println("create object");
    }

    public void getPerson(){
        personService.getPerson();
    }
}

PersonService.java

package com.mashibing.service;

import com.mashibing.dao.PersonDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class PersonService {

    @Autowired
    private PersonDao personDao;

    public void getPerson(){
        personDao.getPerson();
    }
}

PersonDao.java

package com.mashibing.dao;

        import org.springframework.stereotype.Repository;

@Repository
public class PersonDao {

    public void getPerson(){
        System.out.println("PersonDao:getPerson");
    }
}

Note: when AutoWired annotation is used, automatic assembly is implemented according to type.

1. If only one is found, assign the value directly,

2. If it is not found, an exception will be thrown directly,

3. If more than one is found, it will continue to match according to the variable name as the id,

1. Assembly directly on matching

2. If there is no match, an exception will be reported directly

PersonServiceExt.java

package com.mashibing.service;

import com.mashibing.dao.PersonDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class PersonServiceExt extends PersonService{

    @Autowired
    private PersonDao personDao;

    public void getPerson(){
        System.out.println("PersonServiceExt......");
        personDao.getPerson();
    }
}

PersonController.java

package com.mashibing.controller;

import com.mashibing.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class PersonController {

    @Autowired
    private PersonService personServiceExt;

    public PersonController() {
        System.out.println("create object");
    }

    public void getPerson(){
        personServiceExt.getPerson();
    }
}

You can also use the @ Qualifier annotation to specify the name of the id so that spring does not use the variable name. There are two cases when using the @ Qualifier annotation:

1. If found, assemble directly

2. If it cannot be found, an error will be reported

PersonController.java

package com.mashibing.controller;

import com.mashibing.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;

@Controller
public class PersonController {

    @Autowired
    @Qualifier("personService")
    private PersonService personServiceExt2;

    public PersonController() {
        System.out.println("create object");
    }

    public void getPerson(){
        personServiceExt2.getPerson();
    }
}

Through the above code, we can find that @ AutoWired can certainly be assembled. If it is not assembled, an error will be reported.

4. @ AutoWired can be defined on the method

When we look at the source code of @ AutoWired annotation, we find that this annotation can be used not only on member variables, but also on methods.

PersonController.java

package com.mashibing.controller;

import com.mashibing.dao.PersonDao;
import com.mashibing.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;

@Controller
public class PersonController {

    @Qualifier("personService")
    @Autowired
    private PersonService personServiceExt2;

    public PersonController() {
        System.out.println("create object");
    }

    public void getPerson(){
        System.out.println("personController..."+personServiceExt2);
//        personServiceExt2.getPerson();
    }

     /**
     * When there is @ AutoWired annotation on the method:
     *  1,This method will be called automatically when the bean is created
     *  2,Each parameter of this method is automatically injected with a value
     * @param personDao
     */
    @Autowired
    public void test(PersonDao personDao){
        System.out.println("This method is called:"+personDao);
    }
    
    /**
     * @Qualifier Annotations can also act on attributes to be used as IDs to match objects in the container, if not
     * If this annotation is used, match directly by type
     * @param personService
     */
    @Autowired
    public void test2(@Qualifier("personServiceExt") PersonService personService){
        System.out.println("This method is called:"+personService);
    }
}

5. Annotation for auto assembly @ AutoWired, @ Resource

When using automatic assembly, besides @ AutoWired annotation, you can also use @ Resource annotation. You need to know the difference between the two annotations.

1. @ AutoWired: is the annotation provided in spring, @ Resource: is the annotation defined in the jdk, which relies on the java standard

2. By default, @ AutoWired is assembled by type. By default, dependent objects must exist. By default, @ Resource is matched by name, and the name attribute can be specified.

3. @ AutoWired is only suitable for spring framework, and @ Resource has better scalability

PersonController.java

package com.mashibing.controller;

import com.mashibing.dao.PersonDao;
import com.mashibing.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;

import javax.annotation.Resource;

@Controller
public class PersonController {

    @Qualifier("personService")
    @Resource
    private PersonService personServiceExt2;

    public PersonController() {
        System.out.println("create object");
    }

    public void getPerson(){
        System.out.println("personController..."+personServiceExt2);
        personServiceExt2.getPerson();
    }

    /**
     * When there is @ AutoWired annotation on the method:
     *  1,This method will be called automatically when the bean is created
     *  2,Each parameter of this method is automatically injected with a value
     * @param personDao
     */
    @Autowired
    public void test(PersonDao personDao){
        System.out.println("This method is called:"+personDao);
    }

    /**
     * @Qualifier Annotations can also act on attributes to be used as IDs to match objects in the container, if not
     * If this annotation is used, match directly by type
     * @param personService
     */
    @Autowired
    public void test2(@Qualifier("personServiceExt") PersonService personService){
        System.out.println("This method is called:"+personService);
    }
}

6. Generic dependency injection

In order to explain generic dependency injection, we need to write a basic case first according to our previous knowledge:

Student.java

package com.mashibing.bean;

public class Student {
}

Teacher.java

package com.mashibing.bean;

public class Teacher {
}

BaseDao.java

package com.mashibing.dao;

import org.springframework.stereotype.Repository;

@Repository
public abstract class BaseDao<T> {

    public abstract void save();
}

StudentDao.java

package com.mashibing.dao;

import com.mashibing.bean.Student;
import org.springframework.stereotype.Repository;

@Repository
public class StudentDao extends BaseDao<Student>{
    public void save() {
        System.out.println("Save students");
    }
}

TeacherDao.java

package com.mashibing.dao;

import com.mashibing.bean.Teacher;
import org.springframework.stereotype.Repository;

@Repository
public class TeacherDao extends BaseDao<Teacher> {
    public void save() {
        System.out.println("Save teacher");
    }
}

StudentService.java

package com.mashibing.service;

import com.mashibing.dao.StudentDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class StudentService {

    @Autowired
    private StudentDao studentDao;

    public void save(){
        studentDao.save();
    }
}

TeacherService.java

package com.mashibing.service;

import com.mashibing.dao.TeacherDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class TeacherService {
    @Autowired
    private TeacherDao teacherDao;

    public void save(){
        teacherDao.save();
    }
}

MyTest.java

import com.mashibing.service.StudentService;
import com.mashibing.service.TeacherService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import javax.sql.DataSource;
import java.sql.SQLException;

public class MyTest {
    public static void main(String[] args) throws SQLException {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        StudentService studentService = context.getBean("studentService",StudentService.class);
        studentService.save();

        TeacherService teacherService = context.getBean("teacherService",TeacherService.class);
        teacherService.save();
    }
}

The above code is a function that we can complete before, but we can think about whether the code of the Service layer can be rewritten:

BaseService.java

package com.mashibing.service;

import com.mashibing.dao.BaseDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

public class BaseService<T> {
    
    @Autowired
    BaseDao<T> baseDao;
    
    public void save(){
        System.out.println("Automatically injected objects:"+baseDao);
        baseDao.save();
    }
}

StudentService.java

package com.mashibing.service;

import com.mashibing.bean.Student;
import com.mashibing.dao.StudentDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class StudentService extends BaseService<Student> {

}

TeacherService.java

package com.mashibing.service;

import com.mashibing.bean.Teacher;
import com.mashibing.dao.TeacherDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class TeacherService extends BaseService<Teacher>{

}

Posted by Archangel915 on Sat, 06 Nov 2021 11:31:22 -0700