IOC/DI configuration management third-party bean and annotation development.

Table of contents

1. IOC/DI configuration management third-party bean

1. Configure third-party beans

2. Load the properties file

3. Core container

2. Annotation development

1. Annotation development defines beans

2. Pure annotation development mode 

3. Annotate development bean scope and life cycle management

4. Annotation development dependency injection 

3. IOC/DI annotation development and management of third-party beans 

1. Annotate development and management of third-party beans

2. Annotation development implements resource injection for third-party beans


1. IOC/DI configuration management third-party bean

1. Configure third-party beans

▶ Implement Druid management

▷ Step 1: Import the dependencies of `druid`

  Add dependencies in pom.xml

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.16</version>
</dependency>

▷ Step 2: Configure third-party beans

  Add the configuration of `DruidDataSource` in the applicationContext.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">

    <!--管理DruidDataSource对象-->
    <bean class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/spring_db"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>

</beans>

▷ Step 3: Obtain the corresponding bean object from the IOC container

public class App {
    public static void main(String[] args) {
       ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
       DataSource dataSource = (DataSource) ctx.getBean("dataSource");
       System.out.println(dataSource);
    }
}

▶ Realize C3P0 management

▷ Step 1: Import `C3P0` dependencies

  Add dependencies in pom.xml

<dependency>
    <groupId>c3p0</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.1.2</version>
</dependency>

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
</dependency>

▷ Step 2: Configure third-party beans

  Add configuration in the applicationContext.xml configuration file

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="com.mysql.jdbc.Driver"/>
    <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring_db"/>
    <property name="user" value="root"/>
    <property name="password" value="root"/>
    <property name="maxPoolSize" value="1000"/>
</bean>

Notice:

 ● The attributes of ComboPooledDataSource are injected through the setter method
 ● If you want to inject attributes, you need to provide setter methods corresponding to the attributes in the ComboPooledDataSource class or its upper class
 ● The four attributes of C3P0 are different from the four attributes of Druid

▷ Note: 

 ● When configuring the attributes of the data connection pool, in addition to injecting the four elements of the database connection, you can also configure many other attributes. You can check which attributes are used when you use them. Generally, the basic four are configured, and others have their own The default value
 of Druid and C3P0. If the mysql driver package is not imported, Druid will not report an error, but C3P0 will report an error, indicating that Druid did not load the driver during initialization, while C3P0 is just the opposite
 . When the getConnection() method of DruidDataSource is called to obtain the connection, an error that the driver class cannot be found will also be reported.

2. Load the properties file

▶ Attributed third-party beans

▷ Step 1: Prepare properties configuration file

  Create a jdbc.properties file under resources and add the corresponding attribute key-value pairs

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/spring_db
jdbc.username=root
jdbc.password=root

▷ Step 2: Open `context` namespace

  Open `context` namespace in 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">
</beans>

▷ Step 3: Load properties configuration file

  Use the tag under the `context` namespace in the configuration file to load the properties configuration file

<context:property-placeholder location="jdbc.properties"/>

▷ Step 4: Complete attribute injection

  Use `${key}` to read the content in the properties configuration file and complete property injection

<?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:property-placeholder location="jdbc.properties"/>
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
</beans>

▶ Read a single property

▷ Step 1: Add the corresponding class in the project

  BookDao and BookDaoImpl classes, and add `name` attribute and setter method in BookDaoImpl class

public interface BookDao {
    public void save();
}

public class BookDaoImpl implements BookDao {
    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public void save() {
        System.out.println("book dao save ..." + name);
    }
}

▷ Step 2: Complete the reading and injection of the configuration file

  Add configuration in applicationContext.xml, `bean configuration management`, `read external properties`, `dependency injection`:

<?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:property-placeholder location="jdbc.properties"/>
    
    <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
        <property name="name" value="${jdbc.driver}"/>
    </bean>
</beans>

▶ Precautions

▷ Question 1: The key of the key-value pair is `username`.

  1. When configuring key-value pairs in properties, if the key is set to `username`

 username=root666

  2. Inject the attribute in 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:property-placeholder location="jdbc.properties"/>
      
      <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
          <property name="name" value="${username}"/>
      </bean>
  </beans>

  3. After running, what is printed on the console is not `root666`, but the user name of your own computer. The reason for the problem is that the `<context:property-placeholder/>` tag will load the environment variables of the system, and the value of the environment variable will be loaded first. Run the following code to view the environment variables of the system:

  public static void main(String[] args) throws Exception{
      Map<String, String> env = System.getenv();
      System.out.println(env);
  }

 solution

<context:property-placeholder location="jdbc.properties" 
    system-properties-mode="NEVER"/>

  system-properties-mode  : Set it to NEVER, which means that the above problems can be solved without loading system properties.

  Another solution is to avoid using `username` as a `key` for properties.

▷ Question 2: When there are multiple properties configuration files that need to be loaded, how to configure them?

  1. Adjust the content of the configuration file, add `jdbc.properties`, `jdbc2.properties` under resources, the content is as follows:

  jdbc.properties

  jdbc.driver=com.mysql.jdbc.Driver
  jdbc.url=jdbc:mysql://127.0.0.1:3306/spring_db
  jdbc.username=root
  jdbc.password=root

  jdbc2.properties

username=root666

2. Modify applicationContext.xml

<!--方式一 -->
<context:property-placeholder location="jdbc.properties,jdbc2.properties" system-properties-mode="NEVER"/>

  ● Method 1: It can be realized. If there are many configuration files, each one needs to be configured

<!--方式二-->
<context:property-placeholder location="*.properties" system-properties-mode="NEVER"/>

  ● Method 2: `*.properties` means that all files ending with properties will be loaded, which can solve the problem of method 1, but it is not standard

<!--方式三 -->
<context:property-placeholder location="classpath:*.properties" system-properties-mode="NEVER"/>

  ● Method 3: Standard way of writing, `classpath:` means searching from the root path, but only the root path of the current project can be queried

<!--方式四-->
<context:property-placeholder location="classpath*:*.properties" system-properties-mode="NEVER"/>

  ● Method 4: Not only the current project can be loaded, but also the properties configuration files under the root path of all projects that the current project depends on can be loaded

▶ Summary

 ● Open the `context` namespace:

 ● Load the properties configuration file:

<context:property-placeholder location="" system-properties-mode="NEVER"/>

 ● Introduce the values ​​in the properties configuration file in applicationContext.xml:

${key}

3. Core container

▶ How containers are created

▷ XML configuration files under the class path: directly load files under the class path

ApplicationContext ctx = 
    new ClassPathXmlApplicationContext("applicationContext.xml");

▷ XML configuration file under the file system: need to write the complete system path

ApplicationContext ctx = 
    new FileSystemXmlApplicationContext("
        D:\\workspace\\spring\\spring_10_container\\
        src\\main\\resources\\applicationContext.xml"); 

▶ Three ways to obtain beans

▷ Method 1: The problem with this method is that type conversion is required every time it is obtained

BookDao bookDao = (BookDao) ctx.getBean("bookDao");

▷ Method 2: This method can solve the problem of type coercion, but one more parameter is added.

BookDao bookDao = ctx.getBean("bookDao",BookDao.class);

▷ Method 3: This method is similar to injection by type in dependency injection. It must be ensured that there can only be one bean object corresponding to this type in the IOC container.

BookDao bookDao = ctx.getBean(BookDao.class);

▶ Container class hierarchy

(1) Double-click `shift` in IDEA and enter BeanFactory

(2) Click to enter the BeanFactory class, ctrl+h, you can view the hierarchical relationship of the following structure

▶ Use of BeanFactory

▷ The specific implementation of using BeanFactory to create an IOC container is:

public class AppForBeanFactory {
    public static void main(String[] args) {
        Resource resources = new ClassPathResource("applicationContext.xml");
        BeanFactory bf = new XmlBeanFactory(resources);
        BookDao bookDao = bf.getBean(BookDao.class);
        bookDao.save();
    }
}

▷ Compare

 ● BeanFactory is lazy loading, it will only be created when the bean object is obtained

 ● ApplicationContext is loaded immediately, and the bean object will be created when the container loads

 ● If the ApplicationContext needs to be lazy-loaded, it only needs to be configured as follows: (plus lazy-init)

<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"  
    lazy-init="true"/>

▶ summary

▷ Container related

 ● BeanFactory is the top-level interface of the IoC container. When the BeanFactory object is initialized, the loaded beans are loaded lazily. The
 ApplicationContext interface is the core interface of the Spring container. The bean is loaded immediately when it is initialized.
 The ApplicationContext interface provides basic bean operation-related methods, which are extended through other interfaces. Function
 ● ApplicationContext interface commonly used initialization class
  ○ ClassPathXmlApplicationContext (commonly used) 
  ○ FileSystemXmlApplicationContext

▷ bean-related

▷ Dependency injection related

2. Annotation development

 1. Annotation development defines beans

▶ Implementation steps

▷ Step 1: Delete the original XML configuration

  Delete the `<bean>` tag in the configuration file

<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>

▷ Step 2: Add annotations to Dao

  Add `@Component` annotation on BookDaoImpl class

@Component("bookDao")
public class BookDaoImpl implements BookDao {
    public void save() {
        System.out.println("book dao save ..." );
    }
}

 ● Note: @Component annotations cannot be added to interfaces, because interfaces cannot create objects.

 ● Correspondence between XML and annotation configuration:

▷ Step 3: Configure Spring's annotation package scanning

  In order for the Spring framework to scan the annotations written on the class, package scanning needs to be performed on 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"
       xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

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

</beans>

● Note:

 1、component-scan:

  ○ component: component, Spring regards the managed bean as a component of itself
  ○ scan: scan

 2. base-package specifies the package path scanned by the Spring framework, and it scans the annotations on all classes in the specified package and its subpackages.

  ○ The more package paths [such as: com.iheima.dao.impl], the smaller the scanning range and the faster the speed
  ○ The fewer the package paths [such as: com.iheima], the larger the scanning range and the slower the speed
  ○ Generally, the scanning range is The organization name of the project is Maven's groupId [eg: com.itheima].

▷ Step 4: Add annotations to Service

  Also add `@Component` to the BookServiceImpl class and hand it over to the Spring framework management

@Component
public class BookServiceImpl implements BookService {
   
}

▷ Step 5: Run the program

 In the App class, obtain the bean object corresponding to BookServiceImpl from the IOC container, and print

public class App {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        //按名称
        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
        System.out.println(bookDao);
        //按类型获取bean
        BookService bookService = ctx.getBean(BookService.class);
        System.out.println(bookService);
    }
}

illustrate :

 ● The BookServiceImpl class does not have a name, so the bean object is obtained according to the type in the App

 ● If the @Component annotation does not have a name, there will be a default value of `the first letter of the current class name is lowercase`, so it can also be obtained by name, such as:

BookService bookService = (BookService)ctx.getBean("bookServiceImpl");
System.out.println(bookService);

● For the @Component annotation, three other annotations `@Controller`, `@Service`, `@Repository` are also derived

  By looking at the source code, you will find: (These three annotations have the same function as @Component annotations, why should these three be derived? In order to facilitate us to distinguish this class when we write the class later. Presentation layer`, `business layer` or `data layer` classes.)

 ● @Component

2. Pure annotation development mode 

▶ Implementation method

 First delete the configuration file applicationContext.xml and replace it with a class.

▷ Step 1: Create a configuration class

 Create a configuration class `SpringConfig`

public class SpringConfig {
}

▷ Step 2: Identify this class as a configuration class

Add the `@Configuration` annotation to the configuration class to identify it as a configuration class, replacing `applicationContext.xml`

@Configuration
public class SpringConfig {
}

▷ Step 3 : Replace Package Scan Configuration with Annotations

Add the package scanning annotation `@ComponentScan` to the configuration class to replace `<context:component-scan base-package=""/>`

@Configuration
@ComponentScan("com.itheima")
public class SpringConfig {
}

▷ Step 4: Create a running class and execute it

Create a new runtime class `AppForAnnotation`

public class AppForAnnotation {
    public static void main(String[] args) {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);

        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
        System.out.println(bookDao);

        BookService bookService = ctx.getBean(BookService.class);
        System.out.println(bookService);
    }
}

Run AppForAnnotation, you can see that the two objects are still successfully obtained.

▶ Summary

 ● Java classes replace Spring core configuration files

 ● @Configuration annotation is used to set the current class as configuration class

 ● The @ComponentScan annotation is used to set the scan path, this annotation can only be added once, please use array format for multiple data

 @ComponentScan({com.itheima.service","com.itheima.dao"})

 ● Switch from reading the Spring core configuration file to initialize the container object to reading the Java configuration class to initialize the container object

//加载配置文件初始化容器
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

//加载配置类初始化容器
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);

● @Configuration

● @ComponentScan 

3. Annotate development bean scope and life cycle management

▶ @Scope annotation

By default, the bean is a singleton. To become a non-singleton, you only need to add `@scope` annotations to its class, such as:

@Repository
//@Scope设置bean的作用范围
@Scope("prototype")
public class BookDaoImpl implements BookDao {

    public void save() {
        System.out.println("book dao save ...");
    }
}

▶ Bean life cycle

● @PostConstruct

● @PreDestroy

● Note: If @PostConstruct and @PreDestroy annotations cannot be found, you need to import the following jar package. The reason why I can't find it is that the javax.annotation package in jdk has been removed since JDK9, and these two annotations happen to be in this package.

<dependency>
  <groupId>javax.annotation</groupId>
  <artifactId>javax.annotation-api</artifactId>
  <version>1.3.2</version>
</dependency>

For example:

@Repository
public class BookDaoImpl implements BookDao {
    public void save() {
        System.out.println("book dao save ...");
    }
    @PostConstruct //在构造方法之后执行,替换 init-method
    public void init() {
        System.out.println("init ...");
    }
    @PreDestroy //在销毁方法之前执行,替换 destroy-method
    public void destroy() {
        System.out.println("destroy ...");
    }
}

To see the two methods executed, it should be noted that `destroy` will only be executed when the container is closed.

▶ Summary

4. Annotation development dependency injection 

● @Autowired

▶ Add dependencies

  pom.xml add Spring dependencies

  <dependencies>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>5.2.10.RELEASE</version>
      </dependency>
  </dependencies>

▶ Annotation implementation is injected according to type

▷ (1) Add the `@Autowired` annotation to the bookDao property of the BookServiceImpl class

@Service
public class BookServiceImpl implements BookService {
    @Autowired
    private BookDao bookDao;
    
//      public void setBookDao(BookDao bookDao) {
//        this.bookDao = bookDao;
//    }
    public void save() {
        System.out.println("book service save ...");
        bookDao.save();
    }
}

Notice:

 ● @Autowired can be written on the attribute or on the setter method. The easiest way to deal with it is `write on the attribute and delete the setter method` ● Why can the setter method be deleted? ○ Autowiring is based on
 reflection
  design Create an object and set values ​​for private properties through violent reflection
  ○ Ordinary reflection can only get public modified content
  ○ Violent reflection can also get private modified content in addition to public modified content
  ○ So there is no need to provide a setter method here

▷ (2) @Autowired is injected according to the type, so if there are multiple implementation classes corresponding to the BookDao interface, such as adding BookDaoImpl2

@Repository
public class BookDaoImpl2 implements BookDao {
    public void save() {
        System.out.println("book dao save ...2");
    }
}

At this time, if you run the App again, an error will be reported. At this time, it is impossible to distinguish which object to inject by type injection. Solution: `Inject by name`.

▶ question

 First give the two Dao classes a name

  @Repository("bookDao")
  public class BookDaoImpl implements BookDao {
      public void save() {
          System.out.println("book dao save ..." );
      }
  }
  @Repository("bookDao2")
  public class BookDaoImpl2 implements BookDao {
      public void save() {
          System.out.println("book dao save ...2" );
      }
  }

At this point, you can inject successfully, but you have to think about a question: 

  ● @Autowired is injected according to the type. It gives names to the two implementations of BookDao. It still has two bean objects. Why does it not report an error? @Autowired is automatically assembled according to the type by default. If multiple beans of the same type are found in the IOC container, Just match the variable name and the Bean name. Because the variable name is `bookDao` and there is also a `booDao` in the container, it can be injected successfully.

  ● Analyze whether the injection can be completed in the following situation?

No, because multiple bean objects will be found according to the type. At this time, it will be searched according to the name of `bookDao`, because the IOC container only has the names `bookDao1` and `bookDao2`, it will not be found, and `NoUniqueBeanDefinitionException` will be reported.

▶ Annotation implementation is injected by name

● @Qualifier

  When multiple beans are found in the container according to the type, and the attribute name of the injected parameter is inconsistent with the name of the bean in the container, how to solve this problem, you need to use `@Qualifier` to specify the bean object of which name to inject.

@Service
public class BookServiceImpl implements BookService {
    @Autowired
    @Qualifier("bookDao1")
    private BookDao bookDao;
    
    public void save() {
        System.out.println("book service save ...");
        bookDao.save();
    }
}

Note: The value after the @Qualifier annotation is the name of the bean that needs to be injected. @Qualifier cannot be used independently and must be used with @Autowired.

▶ Simple data type injection

● @Value

   The simple type injection is a basic data type or a string type. Next, add a `name` attribute to the `BookDaoImpl` class and use it for simple type injection. If the data type is changed, the corresponding annotation should also be changed. This time, use `@Value` annotation and write the value into the parameter of the annotation.

@Repository("bookDao")
public class BookDaoImpl implements BookDao {
    @Value("itheima")
    private String name;
    public void save() {
        System.out.println("book dao save ..." + name);
    }
}

Note that the data format must match, such as injecting "abc" into an int value, and the program will report an error.

▶ Annotation read properties configuration file

● @PropertySource

▷ Step 1: Prepare properties file under resource

name=itheima888

▷ Step 2: Load the properties configuration file using annotations

Add `@PropertySource` annotation on the configuration class

@Configuration
@ComponentScan("com.itheima")
@PropertySource("jdbc.properties")
public class SpringConfig {
}

▷ Step 3: Use @Value to read the content in the configuration file

@Repository("bookDao")
public class BookDaoImpl implements BookDao {
    @Value("${name}")
    private String name;
    public void save() {
        System.out.println("book dao save ..." + name);
    }
}

Notice:

● If there are multiple properties configuration files to read, you can use the attribute of `@PropertySource` to specify multiple

@PropertySource({"jdbc.properties","xxx.properties"})

● Wildcard characters `*` are not supported in `@PropertySource` annotation properties, and an error will be reported when running

@PropertySource({"*.properties"})

● `classpath:` can be added to the `@PropertySource` annotation attribute, which means to find files from the root path of the current project

@PropertySource({"classpath:jdbc.properties"})

3. IOC/DI annotation development and management of third-party beans 

● pom.xml adds Spring dependencies

 <dependencies>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>5.2.10.RELEASE</version>
      </dependency>
  </dependencies>

1. Annotate development and management of third-party beans

● @Bean

▶ Implementation steps

▷ Step 1: Import the corresponding jar package

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.16</version>
</dependency>

▷ Step 2: Add a method in the configuration class

 Note that the return value of this method is the type of Bean object to be created

@Configuration
public class SpringConfig {
    public DataSource dataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
        ds.setUsername("root");
        ds.setPassword("root");
        return ds;
    }
}

▷ Step 3: Add `@Bean` annotation to the method

The function of @Bean annotation is to make the return value of the method as a bean object managed by Spring

@Configuration
public class SpringConfig {
    @Bean
    public DataSource dataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
        ds.setUsername("root");
        ds.setPassword("root");
        return ds;
    }
}

Note: `DataSource ds = new DruidDataSource()` cannot be used, because there is no corresponding setter method in the DataSource interface to set properties.

▷ Step 4: Get the object from the IOC container and print it

public class App {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        DataSource dataSource = ctx.getBean(DataSource.class);
        System.out.println(dataSource);
    }
}

▶ Introduce external configuration classes

● @Import

 For the bean of the data source, we create a `JdbcConfig` configuration class and configure the data source under this class.

public class JdbcConfig {
    @Bean
    public DataSource dataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
        ds.setUsername("root");
        ds.setPassword("root");
        return ds;
    }
}

How can this configuration class be loaded by the Spring configuration class and create a DataSource object in the IOC container?

For this problem, there are two solutions:

▷ import using package scan

● Step 1: Add package scanning to the Spring configuration class

@Configuration
@ComponentScan("com.itheima.config")
public class SpringConfig {
    
}

● Step 2: Add configuration annotations on JdbcConfig

 The JdbcConfig class needs to be placed in the `com.iheima.config` package, which needs to be scanned by the Spring configuration class

@Configuration
public class JdbcConfig {
    @Bean
    public DataSource dataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
        ds.setUsername("root");
        ds.setPassword("root");
        return ds;
    }
}

▷ Use `@Import` to import

● Step 1: Remove the annotations on the JdbcConfig class

public class JdbcConfig {
    @Bean
    public DataSource dataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
        ds.setUsername("root");
        ds.setPassword("root");
        return ds;
    }
}

● Step 2: Introduce in the Spring configuration class

@Configuration
//@ComponentScan("com.itheima.config")
@Import({JdbcConfig.class})
public class SpringConfig {
    
}

Notice:

 ● Scan annotations can be removed

 ● The @Import parameter requires an array, which can import multiple configuration classes.

 ● The @Import annotation can only be written once in the configuration class

2. Annotation development implements resource injection for third-party beans

▶ Inject simple data types

public class JdbcConfig {
    @Value("com.mysql.jdbc.Driver")
    private String driver;
    @Value("jdbc:mysql://localhost:3306/spring_db")
    private String url;
    @Value("root")
    private String userName;
    @Value("password")
    private String password;

	@Bean
    public DataSource dataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
    }
}

▶ Inject reference data types

▷ Step 1: Scan BookDao in SpringConfig

 The purpose of scanning is to allow Spring to manage BookDao, that is to say, to have a bookDao object in the IOC container

@Configuration
@ComponentScan("com.itheima.dao")
@Import({JdbcConfig.class})
public class SpringConfig {
}

▷ Step 2: Add parameters to the method of the JdbcConfig class

@Bean
public DataSource dataSource(BookDao bookDao){
    System.out.println(bookDao);
    DruidDataSource ds = new DruidDataSource();
    ds.setDriverClassName(driver);
    ds.setUrl(url);
    ds.setUsername(userName);
    ds.setPassword(password);
    return ds;
}

Reference type injection only needs to set the formal parameters for the bean definition method, and the container will automatically assemble the object according to the type.

▶ summary

Guess you like

Origin blog.csdn.net/yzh2776680982/article/details/127119874