Spring IOC

什么是Spring

概念:是一款开源轻量级应用程序框架 主要用企业级的构建程序,解决复杂性的业务问题,使用Spring开发可以将Bean对象,Dao组件对象,Service组件对象等交给Spring容器来管理。

作用:提高开发效率,降低代码的耦合度,提高代码的复用性,提高代码的键状性

谈谈Spring的两个核心模块

ioc的概念:控制反转 是一种设计思想 将你设计好的对象交给容器控制

ioc控制反转:将创建好的对象交给容器进行管理,自动组装,管理事务,整合Mybatis

aop的概念: AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。

aop面向切面:在不修改原代码的情况下对业务进行增强。

DI:依赖注入

        理解:DI实际上就是ioc的具体实现

        可以把ioc的容器中的资源进行使用

表现形式 setter注入,构造函数注入, 注解注入

为什么要使用Spring

 1.方便解耦,简化开发 依赖到组件松耦合

 2.AOP编程的支持 面向切面 通知类 通知 切面 连接点

 3. IOC管理对象和组件  xml和注解方式

4.方便程序的测试 可以用过注解去测试某项功能

5.整合各种插件和依赖 如spring-boot-start  mybatis-spriing

Spring的诞生是为了解决什么问题的

为了解决企业级应用开发的业务逻辑层和其他各层的耦合问题

2.基于XML的方式管理Bean

   准备项目

        1.创建一个工程Spring_demo

        2.在pom.xml引入SpringIoc相关的依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.qitai</groupId>
    <artifactId>spring_demo01</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

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

        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.3.1</version>
        </dependency>
    </dependencies>

</project>

创建HappyComponent类

package com.qitai.ioc;

public class HappyComponent {
    public void doWork(){
        System.out.println("Spring Ioc Component");
    }
}

引入Spring-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="happyComponent" class="com.qitai.ioc.HappyComponent"></bean>
</beans>

创建ioc容器

    @Test
    public void setApplicationContext() {
        // 1.创建ioc 并读取配置文件
        ApplicationContext context = new
                ClassPathXmlApplicationContext("spring-bean-01.xml");

        // 2.先创建容器 后配置文件
        ClassPathXmlApplicationContext applicationContext = new
                ClassPathXmlApplicationContext();
        applicationContext.setConfigLocation("spring-bean-01.xml");
        applicationContext.refresh();
    }

获取bean

 @Test
    public void testExperiment() {
        // 第一种创建方式
        //1.创建ioc 读取配置文件
        ApplicationContext applicationContext =
                new ClassPathXmlApplicationContext("spring-bean-01.xml");
        //2.获取bean对象
        HappyComponent happyComponent = applicationContext.getBean("happyComponent", HappyComponent.class);
        //3.调用其方法
        happyComponent.doWork();

        // 第二种创建方式
        // 1.创建容器 加载配置文件
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext();
        // 2.设置配置文件
        context.setConfigLocation("spring-bean-01.xml");
        // 3.后配置文件刷新
        context.refresh();
        // 4.获取bean
        HappyComponent bean = context.getBean("happyComponent", HappyComponent.class);
        bean.doWork();
    }

bean的id是唯一的,bean需要包含了无参构造函数

2.1获取bean的三种方式

  @Test
    public void Methods(){
        // 根据id获取
       // 1.创建容器 加载配置文件
        ClassPathXmlApplicationContext context =
                new ClassPathXmlApplicationContext("spring-bean-01.xml");
        // 2.根据Bean获取Id 返回的是object类型 进行强制转换
        HappyComponent happyComponent = (HappyComponent) context.getBean("happyComponent");
        // 3.调用其方法
        happyComponent.doWork();

        // 根据类获取
        // 1.创建容器 加载配置文件
        ApplicationContext context1 =
                new ClassPathXmlApplicationContext("spring-bean-01.xml");
        // 2.根据bean获取类型
        HappyComponent bean = context1.getBean(HappyComponent.class);
        // 3.调用其方法
        bean.doWork();
        
        // 根据id和类型
        // 1.创建容器 加载配置文件

        ApplicationContext applicationContext=new  ClassPathXmlApplicationContext("spring-bean-01.xml");
        // 2.根据bean获取类型和id
        HappyComponent happyComponents=applicationContext.getBean("happyComponent",HappyComponent.class);
        // 3.调用其方法
        happyComponents.doWork();
    }

2.2 Bean属性赋值: setter注入

        1.组件类添加属性

package com.qitai.ioc;

import lombok.Getter;
import lombok.Setter;

@Setter
@Getter
public class HappyComponent {

    private String componentName;

    public void doWork(){
        System.out.println("Spring Ioc Component");
    }


}

   2. 配置时给属性指定值

<?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">
<!--     id 是唯一的 class是类的路径地址-->
    <bean id="happyComponent3" class="com.qitai.ioc.HappyComponent">
<!--        property属性,方法对象给组件设置属性 -->
<!--        name 指定属性名 value指定属性值-->
        <property name="componentName" value="veryHappy"></property>
    </bean>
</beans>

 3.运行属性的获取bean数据

package com.qitai.ioc;

import lombok.Setter;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;


public class IocBeanThree {
    @Test
    public   void BeanThrees(){
        // 1.创建容器 加载配置文件
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-bean-03.xml");
        // 2.通过bean获取id和class
        HappyComponent happyComponents =
                context.getBean("happyComponent3", HappyComponent.class);
        // 3. 获取属性值对象
        String componentName = happyComponents.getComponentName();
        // 4.输出结果
        System.out.println(componentName);
    }
}

2.4Bean属性赋值引入其他Bean

1.声明先的组件

package com.qitai.ioc;

import lombok.Getter;
import lombok.Setter;

@Setter 
@Getter
public class HappyMachine {
    private String machineName;
}

2.原组件引入新组件

public class HappyComponent {

    //添加属性
    private String componentName;

    public String getComponentName() {
        return componentName;
    }

    //必须配置set方法,属性设置,ioc容器是通过set方法调用,进行属性赋值!!!
    public void setComponentName(String componentName) {
        this.componentName = componentName;
    }
    
    
    
    //引用新组件
    private HappyMachine happyMachine;
    
    public HappyMachine getHappyMachine() {
        return happyMachine;
    }

    public void setHappyMachine(HappyMachine happyMachine) {
        this.happyMachine = happyMachine;
    }

    public void doWork() {
        System.out.println("HappyComponent.doWork");
    }
}

3.在spring-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="happyMachine" class="com.qitai.ioc.HappyMachine">
        <property name="machineName" value="makeHappy"></property>
    </bean>
</beans>

4.组件之间引入配置

<?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">
<!--     id 是唯一的 class是类的路径地址-->
    <bean id="happyMachine" class="com.qitai.ioc.HappyMachine"/>
    <bean id="happyComponent3" class="com.qitai.ioc.HappyComponent">
<!--        property属性,方法对象给组件设置属性 -->
<!--        name 指定属性名 value指定属性值-->
        <property name="componentName" value="veryHappy"/>
<!--        ref属性 通过bean id引入其他bean -->
        <property name="happyMachine" ref="happyMachine"/>
    </bean>

</beans>

5.获取spring-bean04.xml

package com.qitai.ioc;

import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class IocBeanFour {
    @Test
    public void IocBeanFours(){
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-bean-03.xml");

        HappyComponent happyMachine
                = context.getBean("happyComponent3", HappyComponent.class);
        System.out.println(happyMachine.getHappyMachine().getMachineName());
    }
}

2.5内部bean的声明

        1.声明内部的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">
    <bean id="happyComponent5" class="com.qitai.ioc.HappyComponent">
        <property name="happyMachine">
            <bean class="com.qitai.ioc.HappyMachine">
                <property name="machineName" value="makeHappy"></property>
            </bean>
        </property>
    </bean>
</beans>

      2.测试读取bean的内部类

package com.qitai.ioc;

import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class IodBeanFive {

    @Test
    public void  IodBeanFives(){
        // 1.创建容器 加载配置文件
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-bean05.xml");
        //  2.获取id
        HappyComponent happyComponents
                = context.getBean("happyComponent5", HappyComponent.class);
        // 3.先获取内部bean 在获取内部里面的bean
        String machineName = happyComponents.getHappyMachine().getMachineName();
        // 4.运行
        System.out.println(machineName);

        HappyMachine happyMachine = happyComponents.getHappyMachine();
        System.out.println(happyMachine);

        // 没有先获取内部bean 直接获取内部bean里面的bean是无法获取的
        // 会出现运行时异常 NoSuchBeanDefinitionException
        HappyMachine bean = context.getBean(HappyMachine.class);
        System.out.println(bean);
    }
}

2.6 引入外部Properties配置参数

        1.引入依赖 mysql 和druid 

<!-- 数据库驱动 和 连接池-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.25</version>
</dependency>

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

 2.创建外部文件

jdbc.user=root
jdbc.password=root
jdbc.jdbc.url=jdbc:mysql:///news_headline
jdbc.driver=com.mysql.jdbc.Driver

3.引入属性文件

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

4.spring-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"
       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 https://www.springframework.org/schema/context/spring-context.xsd">
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="url" value="${jdbc.url}"></property>
        <property name="driverClassName" value="${jdbc.driver}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

</beans>

5.运行测试获取连接

package com.qitai.ioc;

import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

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

public class JdbcBeanTest {

    @Test
    public void JdbcBeanTests(){
        // 1.创建容器 加载配置文件
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-bean06.xml");
        // 2.获取数据库的bean
        DataSource bean = context.getBean(DataSource.class);
        try {
            // 3.获取连接
            Connection connection = bean.getConnection();
            // 4.运行
            System.out.println(connection);
            //5.关闭连接
            connection.close();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }

    }
}
2.7 FactoryBean特性

 1.FactoryBean使用场景 代理类的创建 第三方框架的整合

2.Factorybean应用

        2.1准备实现factorybean

package com.qitai.facory;

import com.qitai.ioc.HappyMachine;
import org.springframework.beans.factory.FactoryBean;

public class HappyFactoryBean implements FactoryBean<HappyMachine> {

    private  String machineName;

    public String getMachineName() {
        return machineName;
    }

    public void setMachineName(String machineName) {
        this.machineName = machineName;
    }

    @Override
    public HappyMachine getObject() throws Exception {
        // 创建对象
        HappyMachine  happyMachine = new HappyMachine();
        // 设置引入的对象
        happyMachine.setMachineName(this.machineName);
        // 返回引入的对象
        return happyMachine;
    }

    @Override
    public Class<?> getObjectType() {
        // 返回要生产的对象
        return HappyMachine.class;
    }
}

 2.2配置FactoryBean实现类 

<?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="happyFactoryBean" class="com.qitai.facory.HappyFactoryBean">
        <property name="machineName" value="iceCreamMachine"></property>
    </bean>
</beans>

2.3运行代码

package com.qitai.facory;

import com.qitai.ioc.HappyMachine;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class FactoryTest {
    @Test
    public void FactoryTests(){
        // 创建容器 加载配置文件
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-beanfactory.xml");

        //  获取bean加载
        HappyMachine happyMachine7 = context.getBean("happyMachine7", HappyMachine.class);
        // 拿到HappyMachine的bean对象
        System.out.println(happyMachine7);
        // 拿到factoryBean的bean对象
        Object bean = context.getBean("&happyMachine7");
        System.out.println("bean = " + bean);
    }
}

2.3bean的作用域 

1.作用域配置与测试

     配置scope范围

<?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">
<!--        prototype 在ioc容器中有多个实例-->
    <bean id="happyMachine8" scope="prototype" class="com.qitai.ioc.HappyMachine">

        <property name="machineName" value="happyMachine"></property>
    </bean>
<!--    singleton 在ioc容器中对象始终为单例-->
    <bean id="happyComponent8" scope="singleton" class="com.qitai.ioc.HappyComponent">
        <property name="componentName" value="happycomponent"></property>
    </bean>
</beans>

2. 测试读取

package com.qitai.scop;

import com.qitai.ioc.HappyComponent;
import com.qitai.ioc.HappyMachine;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class ScopTest {
    @Test
    public void ScopTests(){
        // 创建容器 加载实例
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-scope-bean.xml");
        // 获取bean对象
        HappyMachine bean = context.getBean(HappyMachine.class);
        HappyMachine beans = context.getBean(HappyMachine.class);
        System.out.println(bean==beans);

        // 获取bean对象
        HappyComponent Hbean = context.getBean(HappyComponent.class);
        HappyComponent Hbeans = context.getBean(HappyComponent.class);
        System.out.println(Hbean==Hbeans);

    }
}

Bean的生命周期

package com.qitai.post;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.lang.Nullable;

public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization");
        System.out.println(bean+"..."+beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization");
        System.out.println(bean+"..."+beanName);
        return bean;
    }
}

 init-method / destroy-method 配置

<?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="myBeanPostProcessor2" class="com.qitai.post.MyBeanPostProcessor" >

    </bean>

    <bean id="myBean"  class="com.qitai.post.MyBeanPostProcessor" init-method="init" destroy-method="destroy"/>
</beans>

测试代码读取配置文件

@Test
public void testExperiment09()  {
    ApplicationContext iocContainer = new ClassPathXmlApplicationContext("spring-bean-09.xml");
}

注解方式管理bean

1.注解的理解,注解本身不能被执行,标记范围在类和方法上,执行被spring加载到实现业务上完成,自动装配来执行功能完成具体操作。

2.扫描的理解,开发人员在哪些地方标注了注解,需要扫描到完成具体的共能操作。

3.准备spring的依赖写到pom.xml中

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.qitai</groupId>
    <artifactId>spring_demo02</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

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

        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.8.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

4.准备组件类

package com.qitai.common;

public class CommonComponent {
}
package com.qitai.controller;

public class CommonComponentController {
}
package com.qitai.service;

public class CommonComponentService {
}
package com.qitai.dao;

public class CommonComponentDao {
}

组件添加标记理解

spring有多个组件,可以标记在类上,将这些定义成springBean注解

组合注解 注解中包含注解

@Component 表示容器的一个注解,可以标记在Controller,Service,Dao上

1.@Repository 该注解标记在数据访问层,和Conponent的工鞥相同

2.@Service 该注解标记在业务层,和Conponent的工鞥相同

3.@Controller 该注解标记在控制层,和Conponent的工鞥相同

在源码中这个三个注解是从@Component注解基础上取出的新的名字

package com.qitai.common;

import org.springframework.stereotype.Component;

@Component
public class CommonComponent {
}
package com.qitai.controller;

import org.springframework.stereotype.Controller;

@Controller
public class CommonComponentController {
}
package com.qitai.service;

import org.springframework.stereotype.Service;

@Service
public class CommonComponentService {

}
package com.qitai.dao;

import org.springframework.stereotype.Repository;

@Repository
public class CommonComponentDao {
}

配置文件的扫描范围

 1.基本扫描配置

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

    <context:component-scan base-package="com.qitai.common"/>
</beans>

2.指定排除组件 

<?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 https://www.springframework.org/schema/context/spring-context.xsd">
    <context:component-scan base-package="com.qitai.common">
<!--        context:exclude-filter 排除规则 type: 根据什么来进行排除 annotation取出注解排除 expression指定排除规则表达式 对于注解来指定全类名即可-->
       <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
</beans>

3.引入类型自动装配

package com.qitai.controller;

import com.qitai.service.CommonComponentService;
import lombok.Getter;
import org.springframework.stereotype.Controller;

@Controller(value = "tianDog")
public class CommonComponentController {
    private CommonComponentService service;

    public  void  getMessage(){
        service.getMessage();
    }

}
package com.qitai.service;

import com.qitai.dao.CommonComponentDao;
import org.springframework.stereotype.Service;

@Service("smallDog")
public class CommonComponentService {

    private CommonComponentDao dao;
    public void getMessage(){
        dao.getMessage();
    }

}
package com.qitai.dao;

import org.springframework.stereotype.Repository;

@Repository
public class CommonComponentDao {

    public void getMessage() {
        System.out.print("I am a soldier");
    }
}

4.实现自动装配

@Autowired  注解标记成员变量

以上代码 成员变量加上@Autowired注解完成自动装配加载在ioc容器中

2.构造器完成自动装配

    @Autowired
    public CommonComponentController( CommonComponentService service){
        this.service = service;
    }

3.setter注入@Autowired注解

    @Autowired
    public void CommonComponentServices(CommonComponentService service){
        this.service =service;
    }

3.工作流程 

Bean属性赋值 :基本属性赋值

@Value 通常进入外部化属性

声明外部配置文件

catalog.name=MovieCatalog

xml引入外部配置

spring-iocNoter.Onexml.xml

@Value注解读取配置

package com.qitai.common;

import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;


@Component
@Data
public class CommonComponent {

    @Value("${catalog:MovieCatalog}")
    private String name;
}

基于配置类的方式管理bean

1.配置类和扫描注解的使用

xml+注解的方式

创建application.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/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <context:component-scan base-package="com.qitai.common.CommonComponent"/>
    <context:property-placeholder location="application.properties"></context:property-placeholder>
</beans>

测试容器的运行结果

    @Test
    public void IocNotesAppcation(){
        ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
        System.out.println(context);
    }

使用配置类注解完成功能

package com.qitai.config;

import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.PropertySource;

@Configurable //标记是当前配置类 使用该注解 application.xml
//使用PropertySource注解可以外部配置文件 替代了 <context:property-placeholder location="application.properties" />
@PropertySource("classes:application.properties")
// 使用ComponentScan 注解可以进行包扫描 替代了  <context:component-scan base-package="com.atguigu.components"/>
@ComponentScan(basePackages = {"com.qitai.common"})
public class MyConfiguration {
}

测试创建IoC容器

    @Test
    public void IocNotesApplicationOne(){
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class);

    }

总结一下注解

@Configurable  被此注解标记的类 是配置类,启动时会自动装配到springIoc中 代替了 application.xml

@PropertySource 此注解标记外部配置文件 ,启动时会自动装配到springioc中 替代了 

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

@ComponentScan 此注解是包扫描,启动是会自动扫描包的内容加载到springioc容器中替代了

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

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


    <!-- 引入外部属性文件 -->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <!-- 实验六 [重要]给bean的属性赋值:引入外部属性文件 -->
    <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="url" value="${jdbc.url}"/>
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="username" value="${jdbc.user}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

</beans>

注解类方式实现

package com.qitai.config;

import com.alibaba.druid.pool.DruidAbstractDataSource;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.PropertySource;

import javax.sql.DataSource;

@Configurable //标记是当前配置类 使用该注解 application.xml
//使用PropertySource注解可以外部配置文件 替代了 <context:property-placeholder location="application.properties" />
@PropertySource({"classes:application.properties","classes:jdbc.properties"})
// 使用ComponentScan 注解可以进行包扫描 替代了  <context:component-scan base-package="com.atguigu.components"/>
@ComponentScan(basePackages = {"com.qitai.common"})
public class MyConfiguration {


    // 配置方式可以使用bean注解+方法返回值
    @Bean
    public DataSource dataSource(@Value("${jdbc.username}") String username,
                                 @Value("${jdbc.password}") String password,
                                 @Value("${jdbc.url}") String url,
                                 @Value("${jdbc.driver}") String driverClassName){
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setUsername(username);
        druidDataSource.setPassword(password);
        druidDataSource.setUrl(url);
        druidDataSource.setDriverClassName(driverClassName);

        return druidDataSource;
    }
}

Bean注解的细节

初始化和销毁指定

package com.qitai.common;

public class Application {

    public  void  init(){
        System.out.println("进行了初始化");
    }
}
package com.qitai.common;

public class ApplicationOne {

    public void destruction(){
        System.out.println("进行了销毁");
    }
}
package com.qitai.common;

import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.Bean;

@Configurable
public class AppConfig {

    @Bean(initMethod = "init")
    public Application a(){

        return new Application();
    }

    @Bean(destroyMethod = "destruction")
    public ApplicationOne b(){
        return new ApplicationOne();
    }



}

@Bean Scope作用域

 @Scope("prototype")
@Import扩展

@import允许从另一个加载bean

package com.qitai.config;

import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;

@Configurable
@Import(ConfigB.class)
public class ConfigA {


    @Bean
    public  A a(){

        return  new A();
    }
}
class A{

}


package com.qitai.config;

import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Repository;

@Configurable
public class ConfigB {

    @Bean
    public B b(){
        return new B();
    }

}
class B{

}
@Conditional扩展 条件注解
package com.qitai.bean;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class User {
    private String name;
    private Integer age;
}
package com.qitai.config;

import com.qitai.bean.User;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.Bean;

@Configurable
public class BeanConfig {

    @Bean(name = "bill")
    public User user(){

        return new  User("bean bill",62);
    }

    @Bean(name = "linus")
    public User userOne(){

        return new  User("bean linus",48);
    }
}
    @Test
    public  void test1(){
        AnnotationConfigApplicationContext applicationContext =
                new AnnotationConfigApplicationContext(BeanConfig.class);
        Map<String, User> beansOfType = applicationContext.getBeansOfType(User.class);
        System.out.println(beansOfType);
    }
package com.qitai.condition;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class LinuxCondition  implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Environment environment = context.getEnvironment();
        String property = environment.getProperty("os.name");
        if (property.contains("Linux")){
            return true;
        }
        return false;
    }
}
package com.qitai.condition;

import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class WindowsCondition  implements Condition {
    //  ConditionContext 判断条件能否使用上下文环境
    // AnnotatedTypeMetadata 注解所在位置的信息
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        // 获取ioc使用bean工厂
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        // 获取类加载器
        ClassLoader classLoader = context.getClassLoader();
        // 获取环境信息
        Environment environment = context.getEnvironment();
        // 获取bean定义的注册类
        BeanDefinitionRegistry registry = context.getRegistry();

        // 获取系统属性名
        String property = environment.getProperty("os.name");
        if (property.contains("Windows")){
            return true;
        }
        return false;
    }
}
package com.qitai.config;

import com.qitai.bean.User;
import com.qitai.condition.LinuxCondition;
import com.qitai.condition.WindowsCondition;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;

@Configurable
public class BeanConfig {

    @Conditional(WindowsCondition.class)
    @Bean(name = "bill")
    public User user(){

        return new  User("bean bill",62);
    }
    @Conditional(LinuxCondition.class)
    @Bean(name = "linus")
    public User userOne(){

        return new  User("bean linus",48);
    }
}

xml和注解,xml加注解配置总结方式

 1.xml的方式

1.1所有的内容都写到xml的配置文件中

2.1声明bean通过<bean></bean>标签

3.1bean中包含基本标签id,class,属性<property name value ref/>

4.1引入外部的properties文件可以通过<context:property-placeholder/>

5.1IoC具体容器实现选择ClassPathXmlApplicationContext对象

2.Xml加注解方式配置总结

2.1 注解负责标记ioc的类进行属性自动装配

2.2xml文件依然需要,需要通过<context:component-scan标签指定注解范围

3.3标记ioc注解@Controller,@Service,@Component,@Repository

3.4标记DI注解:@Autowired @Qualifier @Resource @Value,@Bean

3.5IoC具体容器实现选择ClassPathXmlApplicationContext对象

整合spring6-tset5测试

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.qitai</groupId>
    <artifactId>spring_demo02</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

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

        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.8.2</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
        </dependency>

        <dependency>
            <groupId>jakarta.annotation</groupId>
            <artifactId>jakarta.annotation-api</artifactId>
            <version>2.1.1</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.6</version>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.8.2</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.3.23</version>
        </dependency>
    </dependencies>



<!--    <build>-->

<!--        <resources>-->
<!--            <resource>-->
<!--                <directory>src/main/java</directory>-->
<!--                <includes>-->
<!--                    <include>**/*.xml</include>-->
<!--                    <include>**/*.properties</include>-->
<!--                    <include>**/*.yml</include>-->
<!--                    <include>**/*.p12</include>-->
<!--                </includes>-->
<!--                <filtering>false</filtering>-->
<!--            </resource>-->
<!--            <resource>-->
<!--                <directory>src/main/resources</directory>-->
<!--                <filtering>false</filtering>-->
<!--                <includes>-->
<!--                    <include>**/*.xml</include>-->
<!--                    <include>**/*.yml</include>-->
<!--                    <include>**/*.yaml</include>-->
<!--                    <include>**/*.properties</include>-->
<!--                </includes>-->

<!--            </resource>-->

<!--        </resources>-->
<!--    </build>-->


</project>
package com.qitai;

import com.qitai.bean.User;
import com.qitai.config.BeanConfig;
import com.qitai.config.MyConfiguration;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;

import java.util.Map;
@SpringJUnitConfig(BeanConfig.class)
public class IocNotes {
    @Test
    public void IocNotesOne(){
        System.out.println("IocNotes...");
    }

    @Test
    public void IocNotesAppcation(){
        ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
        System.out.println(context);
    }

    @Test
    public void IocNotesApplicationOne(){
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class);

    }

    @Test
    public  void test1(){
        AnnotationConfigApplicationContext applicationContext =
                new AnnotationConfigApplicationContext(BeanConfig.class);
        String property = applicationContext.getEnvironment().getProperty("os.name");
        System.out.println("当前系统是"+property);

        Map<String, User> beansOfType = applicationContext.getBeansOfType(User.class);
        System.out.println(beansOfType);
    }

    @Autowired
    User user;
    @Test
    public  void test2(){
        System.out.println(user);
    }

}

  • 24
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值