Spring IOC相关

2024/05/15

IOC将创建对象的权力反转给spring框架,降低了程序的耦合度

Java基础中,一个对象的创建只能是交给反射,因此,IOC底层使用反射。通过反射能做到解耦,(同理于我们定义变量,这个变量的值我们可能会在很多地方使用,但如果我们用的变量名,变量名就像占位符一样,以后变量名的值到底是什么,可以动态的赋值,即真正的变量的值与我们所使用的代码的耦合度降低了,相互间的影响降低了)。ioc使用反射,在运行时确定类型并创建对象,通过反射指定模板,不用写死某个东西,可以通过以后传参的方式将内容传递过去,动态的向模板中传入要实例化的对象。最大限度发挥了Java的灵活性,体现了多态的应用,有利于降低类之间的耦合度

Spring的IOC容器为什么用反射而不用new来创建实例

见博文:http://t.csdnimg.cn/M7sFJ

使用Junit测试的@Test注解的好处:

可以在一个类中进行不同的单元测试(相当于在一个类中有了很多个不同的main方法),可以避免经常编写测试类

ApplicationContext 中有哪两个类,这两个类有什么区别

ApplicationContext接口,是工厂接口,使用该接口可以获取到具体的bean对象,该接口下有两个具体的实现类

  1. ClassPathXmlApplicationContext,加载类路径下的spring配置文件(常用)
  2. FileSystemXmlApplicationContext,加载本地磁盘下的spring配置文件(让配置文件与项目分离管理,不常用)

bean管理的相关属性

  • id属性:给bean起的名字,唯一性,
    • id取值要求:必须以字母开始,可以用字母,数字,连字符、下划线,不能出现特殊字符
  • class属性:bean对象的全路径
  • scop属性:bean对象的作用范围
    • singleton 单例(默认) 最常用的方式,生命周期跟配置文件一样,一加载配置文件,实例就创建
    • prototype 多例 不常用 不是加载配置文件的时候创建实例,而是获取实例时,才创建实例
    • request 多例 不常用 应用在web项目中,每次http请求都会创建一个新的实例
    • session 多例 不常用 应用在web项目中,同一个http session共享一个实例
  • init-method:bean对象创建时可以配置一个方法并自动调用
  • destory-method:bean对象销毁时可以配置一个指定方法并自动调用

bean的scope的单例和多例生命周期相关理解:

业务层构造方法
在这里插入图片描述
仅创建动态工厂:
在这里插入图片描述

在这里插入图片描述

实例化对象的三种方式

  1. 默认是无参构造方法(默认方法,基本上都是用这种)

    IOC底层反射默认调用无参构造方法,创建实例的时候必须显式的写出无参构造方法

  2. 静态工厂实例化方式(好处是可以自己编写业务逻辑)

  3. 实例化工厂(动态工厂)实例化方法(好处是可以自己编写业务逻辑)

2024/05/16

DI注入

Dependency Injection 依赖注入

在spring框架负责创建bean对象时,动态地将依赖对象注入到其他bean对象中,即给对象赋值,本质就是等号赋值

依赖注入的方式

1.属性set方法注入值

在这里插入图片描述

property标签的使用

  • 简单类型(基本类型+字符串) property标签使用value属性赋值;
  • 自定义引用类型 property标签使用ref属性赋值
2.属性的构造方法注入值

既要写有参构造器,也要写无参构造器
在这里插入图片描述
constructor-arg标签的使用

  • 简单类型(基本类型+字符串) constructor-arg标签使用value属性赋值;
  • 自定义引用类型 constructor-arg标签使用ref属性赋值

下述报错原因:只写了有参构造方法,没有写无参构造方法
在这里插入图片描述

3.数组依赖注入值
  • 不可变数组

property标签+array标签+多个value标签

//    不可变数组
    private String[] strs;
  • 可变数组

property标签+list标签+多个value标签

//    可变数组
    private List<String> list;

在这里插入图片描述

4.map依赖注入值

property标签+map标签+多个entry标签

//    map
    private Map<String,String> map;

在这里插入图片描述

5.属性properties依赖注入值

property标签+props标签+多个prop标签

//    properties
    private Properties properties;

在这里插入图片描述

6.自定义引用类型数组

property标签+array标签+多个bean标签

//    自定义类型
    private UserService[] userServices;

在这里插入图片描述

数组、map、properties、注入值 、自定义引用类型数组打印结果
在这里插入图片描述

多配置文件

多配置文件加载方式
在这里插入图片描述

使用spring在数据库中查询数据

bean管理和依赖注入的应用
1.dao实现类代码

public class AccountDaoImpl implements AccountDao {
    private DruidDataSource druidDataSource;

    public void setDruidDataSource(DruidDataSource druidDataSource) {
        this.druidDataSource = druidDataSource;
    }

    @Override
    public List<Account> findAll() {
        /*
        //创建连接池
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
        druidDataSource.setUrl("jdbc:mysql://localhost:3306/spring_db");
        druidDataSource.setUsername("root");
        druidDataSource.setPassword("root");
        */

        //定义数据库对象
        DruidPooledConnection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        List<Account> list = new ArrayList<Account>();

        try {
            //获取连接
            conn = druidDataSource.getConnection();
            //编写sql
            String sql = "select * from account";
            //预编译sql
            stmt = conn.prepareStatement(sql);
            //参数设置
            //执行sql语句
            rs = stmt.executeQuery();
            //遍历结果集
            while (rs.next()) {
                Account account = new Account();
                account.setId(rs.getInt("id"));
                account.setName(rs.getString("name"));
                account.setMoney(rs.getDouble("money"));
                list.add(account);
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //关闭连接资源
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        return list;
    }
}

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

<!--    配置连接池对象-->
    <bean id="ds" 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>

<!--    配置service对象-->
    <bean id="as" class="com.qcby.service.impl.AccountServiceImpl">
        <property name="accountDao" ref="ad"/>
    </bean>

<!--    配置dao对象-->
    <bean id="ad" class="com.qcby.dao.impl.AccountDaoImpl">
        <property name="druidDataSource" ref="ds"/>
    </bean>

</beans>

整体流程:

将dao注入到service中,dao中操作数据库,service只要调方法,service内部就将dao调用起来,对应的数据就返回到service。

bean标签中,id可以随便起,name要对应class中相应的有set方法的变量,ref对应定义了上述变量的class类的在配置文件中的id值

2024/05/17

IOC注解式开发

重点:开启注解扫描!!!

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

引例:

@Component(value = "us")
//⬆等价于<bean id="us" class="com.qcby.service.impl.UserServiceImpl"/>
//@Component() 等价于 @Component(value = "userServiceImpl")
public class UserServiceImpl implements UserService {
    @Override
    public void hello() {
        System.out.println("业务层:你好");
    }
}

测试:

public class UserServiceTest {
    @Test
    public void run1() {
        //加载配置文件,开启其配置的注解扫描
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService us = (UserService) ac.getBean("us");
        us.hello();
    }
}

bean管理类常用的4个注解(作用相同,推荐使用在不同的分层上)

  1. @Component 普通的类
  2. @Controller 表现层的类
  3. @Service 业务层的类
  4. @Respository 持久层的类

依赖注入相关注解

与配置相比的优势:不用加set方法或者构造方法

  1. @Value:用于注入简单类型(基本类型+字符串)

  2. @Autowired:默认按类型进行自动装配(自定义引用类型)(即:bean注解是什么名字不重要,是类就行)

  3. @Qualifier:不能单独使用,必须和@Autowired一起使用,不按照类型注入,强制使用名称注入(即:一起使用时,不仅得是相应的类,并且bean注解名称得一致),使用value参数指定名称(自定义引用类型)

    在这里插入图片描述

  4. @Resource:java提供的注解,也可以达到强制使用名称注入的作用,此注解是单独使用的,且用name参数指定名称,不可省略name(@Qualifier使用value指定名称),可以达到@Autowired+@Qualifier的作用

//等价于<bean id="car" class="com.qcby.entity">
@Component
public class Car{
    
}
//等价于<property name="person" ref="kkk"/>
@Resource(name="kkk")
private Person person;

例:

Car类

//等价于<bean id="car" class="com.qcby.entity"/>
@Component
public class Car {
    @Value("奔驰")
    private String name;

    //推荐使用包装类型,因为double默认值为0,也算一个值,Double默认值为null
    @Value("50000.00")
    private Double money;

    /*@Autowired
    //使用@Qualifier
    @Qualifier("kkk")*/
    //等价于<property name="person" ref="kkk"/>
    @Resource(name="kkk")
    private Person person;

    @Override
    public String toString() {
        return "Car{" +
                "name='" + name + '\'' +
                ", money=" + money +
                ", person=" + person +
                '}';
    }
}

Person类

//不使用@Qualifier或者@Resource
//@Component
//使用@Qualifier或者@Resource
@Component("kkk")
public class Person {
    @Value("张三")
    private String pname;

    @Override
    public String toString() {
        return "Person{" +
                "pname='" + pname + '\'' +
                '}';
    }
}

测试类

public class UserServiceTest {
    @Test
    public void run1() {
        //加载配置文件,开启其配置的注解扫描
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

        Car car = (Car) ac.getBean("car");
        System.out.println(car);
    }
}

生命周期注解

  1. @Scope:取值 singleton(单例) prototype(多例)

    随着配置文件的创建而创建,获取对象的时候才创建

    如下图,若只是读取配置文件,单例时下述方法会执行,多例时不会执行
    在这里插入图片描述

初始化方法和销毁方法

  1. @PostConstruct:相当于init-method 该注解作用到方法上

  2. @PreDestory:相当于destory-method 该注解作用到方法上

    单例时:配置文件加载后,无需等所在类创建,就将该方法调用起来

    在这里插入图片描述

    多例时:所在类创建后,就将该初始化方法调用起来
    在这里插入图片描述

IOC纯注解开发

即:使用配置类代替配置文件

  1. @Configuration:声明当前类为配置类
  2. @ComponentScan(“包名”):扫描指定的包路径
  3. @Import:若有多个配置类,在主配置类中使用该注解导入其他配置类
  4. @Bean:只能写到方法上,表明使用此方法创建一个对象,并把创建好的对象保存到IOC容器中
@Bean
public DruidDataSource createDataSource() {
    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;
}

/*等价于
<bean id="ds" 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>
* */

创建工厂加载配置类

new AnnotationConfigApplicationContext(SpringConfig.class)

Ctrl+H查看继承体系

在这里插入图片描述

配置文件vs配置类

//加载配置文件
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//加载配置类
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
2024/05/18

Spring整合Junit

目的:简化测试开发
步骤:

  1. 导入依赖 spring-test
  2. @RunWith(SpringJUnit4ClassRunner.class) 声明测试类为spring整合junit的类
  3. @ContextConfiguration("classpath:applicationContext.xml") 加载配置文件
  4. @Autowired 注入要用于测试的类

导入依赖

<!--spring整合junit-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.0.2.RELEASE</version>
    <scope>test</scope>
</dependency>

在这里插入图片描述

Spring整合Junit纯注解开发

其他步骤与上述一致,只是

@ContextConfiguration("classpath:applicationContext.xml") 加载配置文件

更改为

@ContextConfiguration("classes:SpringConfig.class") 加载配置类
在这里插入图片描述
-------End!-------

  • 56
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值