IOC/DI配置管理第三方bean及注解开发。

news2024/12/25 8:55:08

目录

一、IOC/DI 配置管理第三方bean

1、配置第三方bean

2、加载properties 文件

3、核心容器

二、注解开发

1、注解开发定义bean

2、纯注解开发模式 

3、注解开发bean作用范围与生命周期管理

4、注解开发依赖注入 

三、IOC/DI注解开发管理第三方bean 

1、注解开发管理第三方bean

2、注解开发实现为第三方bean注入资源


一、IOC/DI 配置管理第三方bean

1、配置第三方bean

▶ 实现Druid管理

▷ 步骤1 : 导入`druid`的依赖

  pom.xml中添加依赖

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

▷ 步骤2 : 配置第三方bean

  在applicationContext.xml配置文件中添加`DruidDataSource`的配置

<?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>

▷ 步骤3 : 从IOC容器中获取对应的bean对象

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);
    }
}

▶ 实现C3P0管理

▷ 步骤1 : 导入`C3P0`的依赖

  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>

▷ 步骤2 : 配置第三方bean

  在applicationContext.xml配置文件中添加配置

<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>

注意:

 ● ComboPooledDataSource的属性是通过setter方式进行注入
 ● 想注入属性就需要在ComboPooledDataSource类或其上层类中有提供属性对应的setter方法
 ● C3P0的四个属性和Druid的四个属性是不一样的

▷ 注意: 

 ● 数据连接池在配置属性的时候,除了可以注入数据库连接四要素外还可以配置很多其他的属性,具体都有哪些属性用到的时候再去查,一般配置基础的四个,其他都有自己的默认值
 ● Druid 和 C3P0在没有导入mysql驱动包的前提下,Druid不会报错,C3P0会报错,说明Druid在初始化的时候没有去加载驱动,而C3P0刚好相反
 ● Druid程序运行虽然没有报错,但是当调用DruidDataSource的getConnection()方法获取连接的时候,也会报找不到驱动类的错误。

2、加载properties 文件

▶ 第三方bean属性化

▷ 步骤1 : 准备properties配置文件

  resources下创建一个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

▷ 步骤2 : 开启`context`命名空间

  在applicationContext.xml中开`context`命名空间

<?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>

▷ 步骤3 : 加载properties配置文件

  在配置文件中使用`context`命名空间下的标签来加载properties配置文件

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

▷ 步骤4 : 完成属性注入

  使用`${key}`来读取properties配置文件中的内容并完成属性注入

<?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>

▶ 读取单个属性

▷ 步骤1 : 在项目中添对应的类

  BookDao和BookDaoImpl类,并在BookDaoImpl类中添加`name`属性与setter方法

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);
    }
}

▷ 步骤2 : 完成配置文件的读取与注入

  在applicationContext.xml添加配置,`bean的配置管理`、`读取外部properties`、`依赖注入`:

<?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>

▶ 注意事项

▷ 问题一 : 键值对的key为`username`引发的问题

  1.在properties中配置键值对的时候,如果key设置为`username`

 username=root666

  2.在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.运行后,在控制台打印的却不是`root666`,而是自己电脑的用户名。出现问题的原因是`<context:property-placeholder/>` 标签会加载系统的环境变量,而且环境变量的值会被优先加载。运行下面的代码查看系统的环境变量:

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

 解决方案

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

  system-properties-mode : 设置为NEVER,表示不加载系统属性,就可以解决上述问题。

  还有一个解决方案就是避免使用`username`作为属性的`key`。

▷ 问题二 : 当有多个properties配置文件需要被加载,该如何配置?

  1.调整下配置文件的内容,在resources下添加`jdbc.properties`,`jdbc2.properties`,内容如下:

  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.修改applicationContext.xml

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

  ● 方式一 : 可以实现,如果配置文件多的话,每个都需要配置

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

  ● 方式二 : `*.properties` 代表所有以properties结尾的文件都会被加载,可以解决方式一的问题,但是不标准

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

  ● 方式三 : 标准的写法,`classpath:`代表的是从根路径下开始查找,但是只能查询当前项目的根路径

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

  ● 方式四 : 不仅可以加载当前项目还可以加载当前项目所依赖的所有项目的根路径下的properties配置文件

▶ 小结

 ● 开启`context`命名空间:

 ● 加载properties配置文件:

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

 ● 在applicationContext.xml引入properties配置文件中的值:

${key}

3、核心容器

▶ 容器的创建方式

▷ 类路径下的XML配置文件:直接加载类路径下的文件

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

▷ 文件系统下的XML配置文件:需要写完整的系统路径

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

▶ bean 获取的三种方式

▷ 方式一 :这种方式存在的问题是每次获取的时候都需要进行类型转换

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

▷ 方式二:这种方式可以解决类型强转问题,但是参数又多加了一个。

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

▷ 方式三 : 这种方式就类似依赖注入中的按类型注入。必须要确保IOC容器中该类型对应的bean对象只能有一个。

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

▶ 容器类层次结构

(1)在IDEA中双击`shift`,输入BeanFactory

(2)点击进入BeanFactory类,ctrl+h,就能查看到如下结构的层次关系

▶ BeanFactory的使用

▷ 使用BeanFactory来创建IOC容器的具体实现方式为:

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();
    }
}

▷ 对比

 ● BeanFactory是延迟加载,只有在获取bean对象的时候才会去创建

 ● ApplicationContext是立即加载,容器加载的时候就会创建bean对象

 ● ApplicationContext要想成为延迟加载,只需要按照如下方式进行配置:(加上 lazy-init)

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

▶ 总结

▷ 容器相关

 ● BeanFactory是IoC容器的顶层接口,初始化BeanFactory对象时,加载的bean延迟加载
 ● ApplicationContext接口是Spring容器的核心接口,初始化时bean立即加载
 ● ApplicationContext接口提供基础的bean操作相关方法,通过其他接口扩展其功能
 ● ApplicationContext接口常用初始化类
  ○  ClassPathXmlApplicationContext(常用) 
  ○ FileSystemXmlApplicationContext

▷ bean相关

▷ 依赖注入相关

二、注解开发

 1、注解开发定义bean

▶ 实现步骤

▷ 步骤1 : 删除原XML配置

  将配置文件中的`<bean>`标签删除掉

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

▷ 步骤2 : Dao上添加注解

  在BookDaoImpl类上添加`@Component`注解

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

 ● 注意 : @Component注解不可以添加在接口上,因为接口是无法创建对象的。

 ● XML与注解配置的对应关系:

▷ 步骤3 : 配置Spring的注解包扫描

  为了让Spring框架能够扫描到写在类上的注解,需要在配置文件上进行包扫描

<?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>

● 注意:

 1、component-scan:

  ○ component : 组件,Spring将管理的bean视作自己的一个组件
  ○ scan:扫描

 2、base-package指定Spring框架扫描的包路径,它会扫描指定包及其子包中的所有类上的注解。

  ○ 包路径越多[如:com.itheima.dao.impl],扫描的范围越小速度越快
  ○ 包路径越少[如:com.itheima],扫描的范围越大速度越慢
  ○ 一般扫描到项目的组织名称即Maven的groupId下[如:com.itheima]即可。

▷ 步骤4 : Service上添加注解

  在BookServiceImpl类上也添加`@Component`交给Spring框架管理

@Component
public class BookServiceImpl implements BookService {
   
}

▷ 步骤5 : 运行程序

 在App类中,从IOC容器中获取BookServiceImpl对应的bean对象,打印

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);
    }
}

说明 :

 ● BookServiceImpl类没有起名称,所以在App中是按照类型来获取bean对象

 ● @Component注解如果不起名称,会有一个默认值就是`当前类名首字母小写`,所以也可以按照名称获取,如:

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

● 对于@Component注解,还衍生出了其他三个注解`@Controller`、`@Service`、`@Repository`

  通过查看源码会发现:(这三个注解和@Component注解的作用是一样的,为什么要衍生出这三个呢?为了方便我们后期在编写类的时候能很好的区分出这个类是属于`表现层`、`业务层`还是`数据层`的类。)

 ● @Component

2、纯注解开发模式 

▶ 实现方式

 首先将配置文件applicationContext.xml删除掉,使用类来替换。

▷ 步骤1 : 创建配置类

 创建一个配置类`SpringConfig`

public class SpringConfig {
}

▷ 步骤2 : 标识该类为配置类

在配置类上添加`@Configuration`注解,将其标识为一个配置类,替`applicationContext.xml`

@Configuration
public class SpringConfig {
}

▷ 步骤3 : 用注解替换包扫描配置

在配置类上添加包扫描注解`@ComponentScan`替换`<context:component-scan base-package=""/>`

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

▷ 步骤4 : 创建运行类并执行

创建一个新的运行类`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);
    }
}

运行AppForAnnotation,可以看到两个对象依然被获取成功。

▶ 小总结

 ● Java类替换Spring核心配置文件

 ● @Configuration注解用于设定当前类为配置类

 ● @ComponentScan注解用于设定扫描路径,此注解只能添加一次,多个数据请用数组格式

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

 ● 读取Spring核心配置文件初始化容器对象切换为读取Java配置类初始化容器对象

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

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

● @Configuration

● @ComponentScan 

3、注解开发bean作用范围与生命周期管理

▶ @Scope 注解

默认情况下bean是单例,要想变成非单例,只需要在其类上添加`@scope`注解,列如:

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

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

▶ Bean的生命周期

● @PostConstruct

● @PreDestroy

● 注意 : @PostConstruct和@PreDestroy注解如果找不到,需要导入下面的jar包。找不到的原因是,从JDK9以后jdk中的javax.annotation包被移除了,这两个注解刚好就在这个包中。

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

例如:

@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 ...");
    }
}

要想看到两个方法执行,需要注意的是`destroy`只有在容器关闭的时候,才会执行。

▶ 小结

4、注解开发依赖注入 

● @Autowired

▶ 添加依赖

  pom.xml 添加Spring的依赖

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

▶ 注解实现按照类型注入

▷ (1) 在BookServiceImpl类的bookDao属性上添加`@Autowired`注解

@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();
    }
}

注意:

 ● @Autowired可以写在属性上,也可也写在setter方法上,最简单的处理方式是`写在属性上并将setter方法删除掉`
 ● 为什么setter方法可以删除呢?
  ○ 自动装配基于反射设计创建对象并通过暴力反射为私有属性进行设值
  ○ 普通反射只能获取public修饰的内容
  ○ 暴力反射除了获取public修饰的内容还可以获取private修改的内容
  ○ 所以此处无需提供setter方法

▷ (2)@Autowired是按照类型注入,那么对应BookDao接口如果有多个实现类,比如添加BookDaoImpl2

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

这个时候再次运行App,就会报错,此时,按照类型注入就无法区分到底注入哪个对象,解决方案:`按照名称注入`。

▶ 问题

 先给两个Dao类分别起个名称

  @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" );
      }
  }

此时就可以注入成功,但是得思考个问题: 

  ● @Autowired是按照类型注入的,给BookDao的两个实现起了名称,它还是有两个bean对象,为什么不报错? @Autowired默认按照类型自动装配,如果IOC容器中同类的Bean找到多个,就按照变量名和Bean的名称匹配。因为变量名叫`bookDao`而容器中也有一个`booDao`,所以可以成功注入。

  ● 分析下面这种情况是否能完成注入呢?

不行,因为按照类型会找到多个bean对象,此时会按照`bookDao`名称去找,因为IOC容器只有名称叫`bookDao1`和`bookDao2`,会找不到,会报`NoUniqueBeanDefinitionException`异常。

▶ 注解实现按照名称注入

● @Qualifier

  当根据类型在容器中找到多个bean,注入参数的属性名又和容器中bean的名称不一致,这个时候该如何解决,就需要使用到`@Qualifier`来指定注入哪个名称的bean对象。

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

注意:@Qualifier注解后的值就是需要注入的bean的名称。@Qualifier不能独立使用,必须和@Autowired一起使用。

▶ 简单数据类型注入

● @Value

   简单类型注入的是基本数据类型或者字符串类型,下面在`BookDaoImpl`类中添加一个`name`属性,用其进行简单类型注入。数据类型换了,对应的注解也要跟着换,这次使用`@Value`注解,将值写入注解的参数中就行了

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

注意数据格式要匹配,如将"abc"注入给int值,这样程序就会报错。

▶ 注解读取properties配置文件

● @PropertySource

▷ 步骤1:resource下准备properties文件

name=itheima888

▷ 步骤2 : 使用注解加载properties配置文件

在配置类上添加`@PropertySource`注解

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

▷ 步骤3:使用@Value读取配置文件中的内容

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

注意:

● 如果读取的properties配置文件有多个,可以使用`@PropertySource`的属性来指定多个

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

● `@PropertySource`注解属性中不支持使用通配符`*`,运行会报错

@PropertySource({"*.properties"})

● `@PropertySource`注解属性中可以把`classpath:`加上,代表从当前项目的根路径找文件

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

三、IOC/DI注解开发管理第三方bean 

● pom.xml添加Spring的依赖

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

1、注解开发管理第三方bean

● @Bean

▶ 实现步骤

▷ 步骤1 : 导入对应的jar包

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

▷ 步骤2 : 在配置类中添加一个方法

 注意该方法的返回值就是要创建的Bean对象类型

@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;
    }
}

▷ 步骤3 : 在方法上添加`@Bean`注解

@Bean注解的作用是将方法的返回值制作为Spring管理的一个bean对象

@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;
    }
}

注意 : 不能使用`DataSource ds = new DruidDataSource()`,因为DataSource接口中没有对应的setter方法来设置属性。

▷ 步骤4 : 从IOC容器中获取对象并打印

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);
    }
}

▶ 引入外部配置类

● @Import

 对于数据源的bean,我们新建一个`JdbcConfig`配置类,并把数据源配置到该类下。

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;
    }
}

这个配置类如何能被Spring配置类加载到,并创建DataSource对象在IOC容器中?

针对这个问题,有两个解决方案:

▷ 使用包扫描引入

● 步骤1 : 在Spring的配置类上添加包扫描

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

● 步骤2 : 在JdbcConfig上添加配置注解

 JdbcConfig类要放入到`com.itheima.config`包下,需要被Spring的配置类扫描到即可

@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;
    }
}

▷ 使用`@Import`引入

● 步骤1 : 去除JdbcConfig类上的注解

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;
    }
}

● 步骤2 : 在Spring配置类中引入

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

注意:

 ● 扫描注解可以移除

 ● @Import参数需要的是一个数组,可以引入多个配置类。

 ● @Import注解在配置类中只能写一次

2、注解开发实现为第三方bean注入资源

▶ 注入简单数据类型

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;
    }
}

▶ 注入引用数据类型

▷ 步骤1 : 在SpringConfig中扫描BookDao

 扫描的目的是让Spring能管理到BookDao,也就是说要让IOC容器中有一个bookDao对象

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

▷ 步骤2 : 在JdbcConfig类的方法上添加参数

@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;
}

引用类型注入只需要为bean定义方法设置形参即可,容器会根据类型自动装配对象。

▶ 总结

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/164810.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深度学习中有哪些从数学模型或相关理论出发, 且真正行之有效的文章?

自深度学习兴起后&#xff0c;深层网路对图像进行特征学习&#xff0c;将低层次的基础特征聚合成更高级的语义特征&#xff0c;取得突出的识别效果&#xff0c;在图像识别、分割及目标检测三大领域得到了众多应用。深度学习算法基本上是由多个网络层搭建&#xff0c;每个网络层…

SpringBoot自动装配

前言 Spring翻译为中文是“春天”&#xff0c;的确&#xff0c;在某段时间内&#xff0c;它给Java开发人员带来过春天&#xff0c;但是随着我们项目规模的扩大&#xff0c;Spring需要配置的地方就越来越多&#xff0c;夸张点说&#xff0c;“配置两小时&#xff0c;Coding五分…

Open3D Usage

Open3D UsageWhat is open3Dopen3D 核心功能包括&#xff1a;python quick start交互指令显示点云**read_point_cloud** ParametersReturnPointCloud的属性&#xff1a;加载ply点云&#xff1a;显示单帧点云&#xff1a;批量单帧显示点云可视化**draw_geometries** Parameters含…

Uniswap v3 详解(三):交易过程

交易过程 v3 的 UniswapV3Pool 提供了比较底层的交易接口&#xff0c;而在 SwapRouter 合约中封装了面向用户的交易接口&#xff1a; exactInput&#xff1a;指定交易对路径&#xff0c;付出的 x token 数和预期得到的最小 y token 数&#xff08;x, y 可以互换&#xff09;e…

Studio One2023新版本更新功能介绍

Studio One 6是一款非常专业的音乐创作编辑软件。为用户提供了所有一切你所需要创作的功能&#xff0c;包括所有的歌曲、项目、仪表板等动能&#xff0c;而且还自定义添加配置文件&#xff0c;良好的界面交互和丰富的功能板块&#xff0c;再结合优秀的性能&#xff0c;能够满足…

基于SpringBoot的SSMP整合(数据层)

模块创建 新建&#xff1a; 添加依赖项&#xff1a; 由于parent没有版本维护&#xff0c;还需在pom.xml文件再次添加&#xff1a; <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version…

Django REST framework--类视图

Django REST framework--类视图基于类的视图APIView类视图generics通用类视图视图集DRF框架路由基于类的视图 项目开发中要不断思考如何让代码保持高内聚&#xff0c;低耦合&#xff0c;因此优化代码的道路上一直都不停歇。目前开发的视图是基于函数形式的&#xff0c;特点是灵…

Effective Objective-C 2.0学习记录(四)

学习记录15.用前缀避免命名空间冲突16.提供“全能初始化方法”17.实现description方法debugDescription&#xff1a;18.尽量使用不可变对象19.使用清晰而协调的命名方式类与协议的命名20.为私有方法名加前缀21.理解OC错误模型22.理解NSCopying协议深拷贝和浅拷贝15.用前缀避免命…

【1-神经网络计算】北京大学TensorFlow2.0

课程地址&#xff1a;【北京大学】Tensorflow2.0_哔哩哔哩_bilibiliPython3.7和TensorFlow2.1六讲&#xff1a;神经网络计算&#xff1a;神经网络的计算过程&#xff0c;搭建第一个神经网络模型神经网络优化&#xff1a;神经网络的优化方法&#xff0c;掌握学习率、激活函数、损…

ArcGIS基础实验操作100例--实验99三维爆炸分析

本实验专栏参考自汤国安教授《地理信息系统基础实验操作100例》一书 实验平台&#xff1a;ArcGIS 10.6 实验数据&#xff1a;请访问实验1&#xff08;传送门&#xff09; 空间分析篇--实验99 三维爆炸分析 目录 一、实验背景 二、实验数据 三、实验步骤 &#xff08;1&…

Open3D ICP精配准(使用鲁棒性核函数,Python版本)

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 标准的ICP算法(点到平面)是使得下面这个目标函数最小化: 其中 p 、 q p、q p、q是相对应的匹配点,

RocketMQ5.0.0路由中心NameServer

一、NameServer概览NameServer是RocketMQ的注册中心&#xff0c;是消息存储Broker、生产者、消费者沟通的桥梁。NameServer集群之间是相互独立的&#xff0c;Broker启动时向所有NameServer注册中心注册。通过DLedger构建NameServer集群&#xff0c;实现如主从切换等功能。启动N…

【笔记】大话设计模式24-28

【笔记】大话设计模式24-28 文章目录【笔记】大话设计模式24-2824 职责链模式24.1 Example24.2 定义24.3 Show me the code24.4 总结25 中介者模式25.1 Example25.2 定义25.3 Show me the code25.4 总结26 享元模式26.1 Example26.2 定义26.3 Show me the code26.4 总结27 解释…

aws s3 参与s3game寻找宝藏游戏挑战学习s3对象存储

参考资料 Pirates S3game workshop http://s3game-level1.s3-website.us-east-2.amazonaws.com/level1.html https://blog.benclmnt.com/notes/s3-game/ https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3/index.html 强烈推荐这种寓教于乐的方式学…

【ROS2 入门】ROS 2 actions 概述

大家好&#xff0c;我是虎哥&#xff0c;从今天开始&#xff0c;我将花一段时间&#xff0c;开始将自己从ROS1切换到ROS2&#xff0c;在上一篇中&#xff0c;我们一起了解ROS 2中Parameters&#xff0c; 这一篇&#xff0c;我们主要会围绕ROS中另外一个重要的概念“Actions ”来…

Linux 系统调用的实现(x86_64)

目录 1、系统调用的定义 1.1 SYSCALL_METADATA宏 1.2 __SYSCALL_DEFINEx定义 2、系统调用表-sys_call_table数组的定义 3、用户态系统调用流程 kernel 5.10 1、系统调用的定义 系统调用的定义我们其实都不陌生&#xff0c;类似这样的函数SYSCALL_DEFINE0&#xff0c; SYSC…

C语言常见错误汇总

1 数组遍历时使用sizeof(a) 任务&#xff1a;有个数组&#xff0c;找出第二大的数&#xff0c;并且打印出来&#xff08;使用*操作数组元素个数&#xff0c;不要使用[]&#xff09; #include<stdio.h> int main01() {int a[] { 100,100,100,234,123,500,32,68,41,99,1…

code.org免费的少儿编程入门平台

现在市面上的少儿编程课&#xff0c;都是先花9.9就能体验几节课&#xff0c;然后要花几千块才能继续学习后面的课程。这些钱大可不必花。 现在给大家推荐一个免费的网站&#xff0c;code.org&#xff0c;它是一个非营利组织创办的网站&#xff0c;目标是让每个学生都能像生物、…

高并发系统设计 --多级缓存

为了提高系统的性能&#xff0c;一般会引入“缓存机制”&#xff0c;将部分热点数据存入缓存中&#xff0c;用空间换取时间&#xff0c;以达到快速响应的目的。 我们对缓存的认知停留在redis&#xff0c;但其实缓存远远不是只有redis的&#xff0c;从客户端发起请求开始&#…

MySQL整体使用》导入数据、约束、多表查询、事务、变量类型、资源占用

我发的MySQL相关内容&#xff1a; C#基础知识体系框架图&#xff0c;及起对应我发过的博客 linux安装mysql8配置使用&#xff0c;并解决常见问题 MySQL常用命令&#xff08;DQL&#xff09; 执行脚本命令&#xff0c;本地生成SQL文件后在服务器执行 // 进入mysql命令控制 m…