02-Spring-IOC

1. IOC容器

  1. 什么是IOC

    对象的创建和对象的调用交由spring去管理,目的是为了降低耦合性

  2. IOC底层实现

    • xml解析、工厂模式、反射

      在这里插入图片描述

  3. IOC 接口

    IOC思想基于IOC容器完成,IOC容器底层就是对象工厂

    Spring提供IOC容器实现两种方式:(两个接口)

    • BeanFactory: Spring内部使用的接口,不提供开发人员进行使用

      *加载配置文件时不会创建对象,在使用对象时才创建对象

    • ApplicationContext: BeanFactory接口的子接口,提供强大的功能,供开发人人员使用

      *加载配置文件时就会创建对象

    • ApplicationContext的实现类
      在这里插入图片描述

      FileSystemXmlApplicationContext 指定全路径加载bean.xml配置文件

      ClassPathXmlApplicationContext 指定类路径加载bean.xml配置文件

    • 如何通过对象工厂获取bean

      @Test
      public void testAdd() {
          ApplicationContext context =
              new ClassPathXmlApplicationContext("classpath:bean1.xml");
          User user = context.getBean("user", User.class);
          System.out.println(user.add(8, 9));
      }
      
      
      @Test
      public void testAdd2() {
          BeanFactory factory =
              new ClassPathXmlApplicationContext("classpath:bean1.xml");
          User user = factory.getBean("user", User.class);
          System.out.println(user.add(1, 2));
      }
      

2. IOC操作bean管理

1. 什么bean管理

  • 创建对象
  • 注入属性

2. bean管理的实现方式

1. 注解方式
  • 需要引入 spring-aop 依赖

  • 开启组件扫描的位置

    <!--
          1.通过context命名空间  开启组件扫描
            如果扫描多个包,用”,“隔开。
            如果多个包的上层目录一样,直接扫描上层目录
        -->
    <context:component-scan base-package=" com.potato2"/>
    
    
    <!--    指定扫描包内的那些内容-->
    <!--
            use-default-filters  默认值为true  扫描包内所有内容
            include-filter  指定扫描的内容
            exclude-filter  指定不扫描的内容
    <context:component-scan base-package="com.potato2" use-default-filters="false">
            <context:include-filter type="annotation"  expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
    此处是指: 只扫描com.potato2 包下 用了 @Controller注解的bean
    -->
    
1. 对象创建
  • @Component
  • @Controller
  • @Service
  • @Repository

上面注解功能一模一样

使用在类上,目的是把bean交由spring来管理

每个注解都有value属性 作用是设置当前bean的名称 默认值为当前类名 首字母小写

//等价于 <bean id="userService" class="com.potato2.service.UserService">
@Component(value = "userService")
public class UserService {
    
}
2. 属性注入

@Autowired 根据属性类型进行注入

@Qualifier 根据属性名称进行注入

@Resource 可以根据属性类型或者名称进行注入 ,默认根据类型注入,通过name属性 进行名称注入

@Value 注入普通数据类型

@Service
public class UserService {

    @Autowired
    private UserDao userDao;

    public void add(int a,int b) {
        userDao.add(a, b);
    }
}

3. 完全注解开发
  1. 创建配置类

    @Configuration //表示当前类是配置类
    @ComponentScan(basePackages = "com.potato2")  //指定扫描的组件位置
    public class SpringConfig {
       
    }
    
  2. 加载配置类

    通过 AnnotationConfigApplicationContext 对象可以加载配置类

    @Test
    public void test02() {
    	ApplicationContext context = 
            new AnnotationConfigApplicationContext(SpringConfig.class);
    }
    
2 .xml实现
1.无参构造、有参构造、基本属性注入、特殊符号注入、NULL值注入
<?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:util="http://www.springframework.org/schema/util"
       xmlns:p="http://www.springframework.org/schema/p"

       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/util
       http://www.springframework.org/schema/util/spring-util.xsd">
    
    <!-- 创建对象  id:对当前bean进行取名  然后通过getBean("idValue",Object.class) 获取-->
    <!-- 需要注入值的属性 需要有set方法 -->
    
    <!-- 1.无参构造-->
    <bean id="user1" class="com.potato.testDemo.User">
        <property name="id" value="1"/>
        <property name="name" value="用户01"/>
        <property name="hobby">
            <list>
                <value>打球</value>
                <value>跑步</value>
                <value>游泳</value>
            </list>
        </property>
    </bean>

    <!--2.有参构造-->
    <bean id="user2" class="com.potato.testDemo.User">
        <constructor-arg name="id" value="2"/>
        <constructor-arg name="name" value="<![CDATA[<<用户02>>]]>"/>/>
        <constructor-arg name="hobby">
            <null></null>
        </constructor-arg>
    </bean>

    <!-- 3. p名称空间注入 配置文件需要引入p名称空间 在set注入上进行的简化-->
    <bean id="user3" class="com.potato.testDemo.User"
          p:id="3" p:name="用户03" p:hobby-ref="hobbyList">
    </bean>


<!-- 特殊符号   可以使用转义字符  &lt;  或者CDATA -->
<!-- <<用户02>>     <![CDATA[<<用户02>>]]>  -->
2.外部bean、内部bean、级联bean
<?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">

    <!--    1.外部bean   ref属性   -->
    <bean id="userDao" class="com.potato.dao.UserDao"/>
    <bean id="userService" class="com.potato.service.UserServiceImpl">
        <property name="userDao" ref="userDao"/>
    </bean>

    <!--    2.内部bean   内部使用bean标签 -->
    <bean name="emp" class="com.potato.pojo.Emp">
        <property name="gender" value="1"/>
        <property name="ename" value="用户1"/>
        <property name="dept">
            <bean class="com.potato.pojo.Dept">
                <property name="dname" value="研发部"/>
            </bean>
        </property>
    </bean>

    <!--    3.级联bean  -->
    <bean name="emp2" class="com.potato.pojo.Emp">
        <property name="gender" value="2"/>
        <property name="ename" value="用户2"/>
        <property name="dept" ref="dept"></property>
        <!--   级联赋值-->
        <property name="dept.dname" value="研发部"></property>
    </bean>
    <bean id="dept" class="com.potato.pojo.Dept"></bean>

</beans>
3. 集合属性注入
<?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">
	<bean id="clazz" class="com.potato.pojo.Clazz">
       <!--    1.注入数组-->
       <property name="courses">
           <array>
               <value>语文</value>
               <value>数学</value>
               <value>英语</value>
           </array>
       </property>
        
       <!--    2.注入List  -->
       <property name="student">
           <list>
               <bean class="com.potato.pojo.User">
                   <property name="id" value="1"/>
                   <property name="name" value="用户1"/>
               </bean>
               <ref bean="user2"/>
           </list>
       </property>
        
       <!--    3.注入Set-->
       <property name="set">
           <list>
               <value>1</value>
          <value>2</value>
               <value>3</value>
          <value>3</value>
           </list>
 	   </property>
        
       <!--    4.注入Map-->
       <property name="map">
           <map>
               <entry key="key01" value="1"/>
               <entry key="key02" value="2"/>
               <entry key="key03" value="3"/>
           </map>
       </property>
   </bean>
</beans>

通过util 命名空间 注入集合

   <?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:util="http://www.springframework.org/schema/util"
          xsi:schemaLocation="http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans.xsd
          http://www.springframework.org/schema/util
     http://www.springframework.org/schema/util/spring-util.xsd">

  <bean id="clazz" class="com.potato.pojo.Clazz">
           <property name="student" ref="student"/>
           <property name="courses" ref="courses"/>
           <property name="set" ref="set"/>
           <property name="map" ref="map"/>
       </bean>
       
   <!-- list\array -->
   <util:list id="courses">
       <value>语文</value>
       <value>数学</value>
       <value>英语</value>
   </util:list>
  
   <!-- set -->
   <util:set id="set">
       <value>易筋经</value>
       <value>九阴真经</value>
       <value>九阳神功</value>
   </util:set>
   
   <!-- map -->
   <util:map id="map">
       <entry key="key01" value="1"/>
       <entry key="key02" value="2"/>
       <entry key="key03" value="3"/>
   </util:map>
  
   <!-- list bean -->
   <util:list id="student">
       <ref bean="user1"/>
       <ref bean="user2"/>
   </util:list>
   <bean id="user1" class="com.potato.pojo.User">
       <property name="id" value="1"/>
       <property name="name" value="用户1"/>
   </bean>
   <bean id="user2" class="com.potato.pojo.User">
       <property name="id" value="2"/>
       <property name="name" value="用户2"/>
   </bean>
</beans>
3. Spring中的两种Bean 普通bean 和 工厂bean(FactoryBean)
  • 普通bean:在配置文件中定义的类型 就是返回的类型

  • 工厂bean:在配置文件中定义的类型 和返回的类型不一样

    1.创建类 实现接口FactoryBean 作为工厂Bean

    2.实现接口里的方法,在方法中返回具体的bean

    bean.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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
                               http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="myBean" class="com.potato.factoryBean.MyBean">
        </bean>
    </beans>
    

    MyBean.java

    public class MyBean implements FactoryBean<User> {
         @Override
         public User getObject() throws Exception {
             // 此方法返回具体的bean 可以根据泛型、反射 返回不同的bean
             return new User(1, "用户1", null);
         }
     
         @Override
         public Class<?> getObjectType() {
             return null;
         }
     
         @Override
         public boolean isSingleton() {
             return FactoryBean.super.isSingleton();
         }
     }
     
    

    测试 Test.java

    //    FactoryBean
    @Test
    public void test9() {
        ApplicationContext context =
            new ClassPathXmlApplicationContext("classpath:beanIOC-FactoryBean.xml");
        User user = context.getBean("myBean", User.class);
        System.out.println(user)
    }
    // myBean 的class 为 MyBean.class  但是我们返回的是User.class
    
4. bean的作用域

Spring里默认的bean是单实例

如何设置多实例

<!--  scope 常用值:   singleton:单实例(默认值) / prototype:多实例-->
 
 <!-- 
 scope 值为 singleton 时,加载配置文件时就完成实例对象的创建
 scope 值为 prototype 时,对象在调用getBean时才创建,每次调用都会产生新的实例对象
 request 
 session 
 -->
 <bean id="user1" class="com.potato.pojo.User" scope="singleton">
     <!--    set 方法注入-->
     <property name="id" value="1"/>
     <property name="name" value="用户01"/>
     <property name="hobby">
         <list>
             <value>打球</value>
             <value>跑步</value>
             <value>游泳</value>
         </list>
     </property>
 </bean>
5. bean的生命周期

第一步 执行无参构造创建bean实例

第二步 调用set方法设置属性值

第三步 执行初始化方法 (需要配置 init-method)

第四步 获取创建bean实例对象

第五步 执行销毁方法 (需要配置 destroy-method)

<bean id="userService" class="com.potato.service.UserServiceImpl" 
      init-method="initMethod" destroy-method="destroyMethod">
    <property name="userDao" ref="userDao"/>
</bean>

销毁发生在 ApplicationContext关闭的时候

ApplicationContext context =
                new ClassPathXmlApplicationContext("bean.xml");
	((ClassPathXmlApplicationContext)context).close();
6. 自动装配

通过value/ref 进行值的配置都属于手动装配

  1. 什么是自动装配

    根据指定装配规则(属性名称、属性类型),spring自动将匹配的属性值进行注入

  2. 如何进行自动装配 配置

    <!--
        实现自动装配
        bean  标签设置autowire
        autowire 常用值
            1.byName    根据属性名称注入,注入值的ID 和 属性名称一样
            2.byType    根据属性类型注入,注入值的class 和属性值的class一样。
        前提条件:注入值的class 只配置了一个bean
    -->
    <bean id="emp" class="com.potato.autowire.Emp" autowire="byType">
        <!--<property name="dept" ref="dept"/>-->
    </bean>
    
    <bean id="dept" class="com.potato.autowire.Dept" />
    
7. 外部属性文件

druid.properties

jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/spring5
jdbc.username=root
jdbc.password=root

bean.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-context.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">

    <!--    
		通过 context名称空间  引入外部文件
		通过 ${} 调用
	-->
    <context:property-placeholder location="druid.properties"/>
    
    <bean class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driverClass}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
</beans>```
posted @   晓洋^  阅读(36)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示