An article to get through the management of beans based on annotations

Table of contents

Turn on component scanning

Case 1: The most basic scanning method  

Case 2: Specify components to exclude

 Case 3: Scan only specified components

Define beans using annotations

@Autowired injection

① Scenario 1: Attribute injection

②Scene 2: set injection

③Scenario 3: Construction method injection

④ Scenario 4: Injection on formal parameters

⑤ Scenario 5: There is only one constructor, no annotations

⑥Scene 6: @Autowired annotation and @Qualifier annotation combined+

Summarize

@Resource injection

① Scenario 1: Inject according to name

②Scene 2: Unknown name injection

③Scene 3 Other situations

Summarize

Spring full annotation development


Starting from Java 5, Java has added support for annotations (Annotation), which is a special mark in the code, which can be read during compilation, class loading and runtime, and perform corresponding processing. Developers can embed supplementary information in source code without changing the original code and logic through annotations.

Spring has provided comprehensive support for annotation technology since version 2.5. We can use annotations to realize automatic assembly and simplify Spring's XML configuration.

The steps for Spring to implement automatic assembly through annotations are as follows:

  1. Introduce dependencies

  2. Turn on component scanning

  3. Define beans using annotations

  4. dependency injection

Turn on component scanning

Spring does not use annotations to assemble beans by default , so we need to enable the automatic scanning function of Spring Beans through the context:component-scan element in Spring's XML configuration. After enabling this function, Spring will automatically scan all classes under the specified package (base-package attribute setting) and its subpackages. If the @Component annotation is used on the class, the class will be assembled into the container.

<?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-3.0.xsd
    http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">
    <!--开启组件扫描功能-->
    <context:component-scan base-package="com.atguigu.spring6"></context:component-scan>
</beans>

 Note: Before using the context:component-scan element to enable the automatic scanning function, you first need to add context-related constraints in the first-level tag <beans> of the XML configuration.

Case 1: The most basic scanning method  

<context:component-scan base-package="com.atguigu.spring6">
</context:component-scan>

Case 2: Specify components to exclude

<context:component-scan base-package="com.atguigu.spring6">
    <!-- context:exclude-filter标签:指定排除规则 -->
    <!-- 
 		type:设置排除或包含的依据
		type="annotation",根据注解排除,expression中设置要排除的注解的全类名
		type="assignable",根据类型排除,expression中设置要排除的类型的全类名
	-->
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        <!--<context:exclude-filter type="assignable" expression="com.atguigu.spring6.controller.UserController"/>-->
</context:component-scan>

 Case 3: Scan only specified components

<context:component-scan base-package="com.atguigu" use-default-filters="false">
    <!-- context:include-filter标签:指定在原有扫描规则的基础上追加的规则 -->
    <!-- use-default-filters属性:取值false表示关闭默认扫描规则 -->
    <!-- 此时必须设置use-default-filters="false",因为默认规则即扫描指定包下所有类 -->
    <!-- 
 		type:设置排除或包含的依据
		type="annotation",根据注解排除,expression中设置要排除的注解的全类名
		type="assignable",根据类型排除,expression中设置要排除的类型的全类名
	-->
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
	<!--<context:include-filter type="assignable" expression="com.atguigu.spring6.controller.UserController"/>-->
</context:component-scan>

Define beans using annotations

Spring provides the following multiple annotations, which can be directly annotated on Java classes to define them as Spring Beans.

annotation illustrate
@Component This annotation is used to describe the Bean in Spring. It is a generalized concept, which only represents a component (Bean) in the container, and can be used at any level of the application, such as the Service layer, Dao layer, etc. When using it, you only need to mark the annotation on the corresponding class.
@Repository This annotation is used to identify the class of the data access layer (Dao layer) as a bean in Spring, and its function is the same as @Component.
@Service This annotation usually acts on the business layer (Service layer), and is used to identify the class of the business layer as a bean in Spring, and its function is the same as that of @Component.
@Controller This annotation usually acts on the control layer (such as the Controller of SpringMVC), and is used to identify the class of the control layer as a bean in Spring, and its function is the same as that of @Component.

@Autowired injection

Use the @Autowired annotation alone, and it will be assembled according to the type by default . [Default is byType]

 source code:

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
    boolean required() default true;
}

There are two things to note in the source code:

  • The first place: Where can the annotation be marked?

  1. On the construction method

  2. Note on
  3. attribute
  4. visit
  5. method
  • The second place: the annotation has a required attribute, the default value is true, which means that the injected Bean must exist during injection, and an error will be reported if it does not exist. If the required attribute is set to false, it doesn't matter whether the injected Bean exists or not. If it exists, it will be injected. If it does not exist, no error will be reported.

① Scenario 1: Attribute injection

Create the UserDao interface

public interface UserDao {

    public void print();
}

Create a UserDaoImpl implementation

@Repository
public class UserDaoImpl implements UserDao {

    @Override
    public void print() {
        System.out.println("Dao层执行结束");
    }
}

Create the UserService interface

public interface UserService {

    public void out();
}

 Create a UserServiceImpl implementation class

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Override
    public void out() {
        userDao.print();
        System.out.println("Service层执行结束");
    }
}

 Create the UserController class

@Controller
public class UserController {

    @Autowired
    private UserService userService;

    public void out() {
        userService.out();
        System.out.println("Controller层执行结束。");
    }

}

test 

public class UserTest {

    private Logger logger = LoggerFactory.getLogger(UserTest.class);

    @Test
    public void testAnnotation(){
        ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
        UserController userController = context.getBean("userController", UserController.class);
        userController.out();
        logger.info("执行成功");
    }

}

 None of the above construction methods and setter methods are provided. After testing, the injection can still be successful.

②Scene 2: set injection

Modify the UserServiceImpl class

@Service
public class UserServiceImpl implements UserService {
    
    private UserDao userDao;
    @Autowired
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void out() {
        userDao.print();
        System.out.println("Service层执行结束");
    }
}

 Modify the UserController class

@Controller
public class UserController {

    private UserService userService;

    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public void out() {
        userService.out();
        System.out.println("Controller层执行结束。");
    }

}

Test: successful call

③Scenario 3: Construction method injection

Modify the UserServiceImpl class

@Service
public class UserServiceImpl implements UserService {

    private UserDao userDao;

    @Autowired
    public UserServiceImpl(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void out() {
        userDao.print();
        System.out.println("Service层执行结束");
    }
}

Modify the UserController class

@Controller
public class UserController {

    private UserService userService;

    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }

    public void out() {
        userService.out();
        System.out.println("Controller层执行结束。");
    }

}

Test: successful call

④ Scenario 4: Injection on formal parameters

Modify the UserServiceImpl class

@Service
public class UserServiceImpl implements UserService {

    private UserDao userDao;

    public UserServiceImpl(@Autowired UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void out() {
        userDao.print();
        System.out.println("Service层执行结束");
    }
}

Modify the UserController class

@Controller
public class UserController {

    private UserService userService;

    public UserController(@Autowired UserService userService) {
        this.userService = userService;
    }

    public void out() {
        userService.out();
        System.out.println("Controller层执行结束。");
    }

}

Test: successful call

⑤ Scenario 5: There is only one constructor, no annotations

Modify the UserServiceImpl class

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    public UserServiceImpl(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void out() {
        userDao.print();
        System.out.println("Service层执行结束");
    }
}

test passed

When there is only one constructor with parameters, the @Autowired annotation can be omitted.

Explanation: What about when there are multiple construction methods? You can test (add another no-argument constructor), and the test will report an error

⑥Scene 6: @Autowired annotation and @Qualifier annotation combined+

 Add dao layer implementation

@Repository
public class UserDaoRedisImpl implements UserDao {

    @Override
    public void print() {
        System.out.println("Redis Dao层执行结束");
    }
}

test: test exception

The error message says: Cannot assemble, the number of Bean UserDao is equal to 2

How to solve this problem? **Of course byName, it is assembled according to the name. **

Modify the UserServiceImpl class

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    @Qualifier("userDaoImpl") // 指定bean的名字
    private UserDao userDao;

    @Override
    public void out() {
        userDao.print();
        System.out.println("Service层执行结束");
    }
}

Summarize

  • The @Autowired annotation can appear on: properties, constructors, parameters of constructors, and setter methods.

  • When there is only one constructor with parameters, the @Autowired annotation can be omitted. ()

  • The @Autowired annotation is injected by type by default. If you want to inject by name, you need to use it with @Qualifier annotation.

@Resource injection

The @Resource annotation can also complete property injection. So what is the difference between it and the @Autowired annotation?

  • The @Resource annotation is in the JDK extension package, which means it is part of the JDK. So this annotation is a standard annotation, which is more general. (Annotation types specified in the JSR-250 standard. JSR is a Java specification proposal.)
  • The @Autowired annotation is Spring Framework's own.
  • The @Resource annotation is assembled byName according to the name by default. When the name is not specified, the attribute name is used as the name. If it is not found by name, it will automatically start assembly by type byType.
  • The @Autowired annotation is assembled byType by type by default. If you want to assemble by name, you need to use it with the @Qualifier annotation.
  • The @Resource annotation is used on properties and setter methods.
  • The @Autowired annotation is used on properties, setter methods, construction methods, and construction method parameters.

The @Resource annotation belongs to the JDK extension package, so it is not included in the JDK, and the following dependencies need to be introduced additionally: [ If it is JDK8, no additional dependencies need to be introduced. If it is higher than JDK11 or lower than JDK8, the following dependencies need to be introduced.

<dependency>
    <groupId>jakarta.annotation</groupId>
    <artifactId>jakarta.annotation-api</artifactId>
    <version>2.1.1</version>
</dependency>

① Scenario 1: Inject according to name

Modify the UserDaoImpl class

@Repository("myUserDao")
public class UserDaoImpl implements UserDao {

    @Override
    public void print() {
        System.out.println("Dao层执行结束");
    }
}

Modify the UserServiceImpl class

@Service
public class UserServiceImpl implements UserService {

    @Resource(name = "myUserDao")
    private UserDao myUserDao;

    @Override
    public void out() {
        myUserDao.print();
        System.out.println("Service层执行结束");
    }
}

②Scene 2: Unknown name injection

Modify the UserDaoImpl class

@Repository("myUserDao")
public class UserDaoImpl implements UserDao {

    @Override
    public void print() {
        System.out.println("Dao层执行结束");
    }
}

Modify the UserServiceImpl class

@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserDao myUserDao;

    @Override
    public void out() {
        myUserDao.print();
        System.out.println("Service层执行结束");
    }
}

 test passed

When the @Resource annotation is used without specifying a name, it is still searched according to the name, which is the attribute name.

③Scene 3 Other situations

@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserDao userDao1;

    @Override
    public void out() {
        userDao1.print();
        System.out.println("Service层执行结束");
    }
}

 test exception

According to the exception information: Obviously, when the name cannot be found, it will naturally start byType for injection. The above error is caused by the fact that there are two implementation classes under the UserDao interface. So injecting according to the type will report an error.

The set injection of @Resource can be tested by itself

Summarize

@Resource annotation: The default is injected byName. When the name is not specified, the attribute name is used as the name. When the name cannot be found, it will be injected byType. When injected byType, there can only be one Bean of a certain type

Spring full annotation development

Full-annotation development is to no longer use the spring configuration file, and write a configuration class to replace the configuration file.

@Configuration
//@ComponentScan({"com.atguigu.spring6.controller", "com.atguigu.spring6.service","com.atguigu.spring6.dao"})
@ComponentScan("com.atguigu.spring6")
public class Spring6Config {
}

 test class

@Test
public void testAllAnnotation(){
    ApplicationContext context = new AnnotationConfigApplicationContext(Spring6Config.class);
    UserController userController = context.getBean("userController", UserController.class);
    userController.out();
    logger.info("执行成功");
}

Guess you like

Origin blog.csdn.net/m0_62436868/article/details/130536950