小白学习spring第一天

news2024/12/22 1:51:54

第二章:Spring

第1节:概述

1.1 介绍 heap stack

Spring是一个分层的Java SE/EE full-stack(一站式)轻量级开源框架,以 IoCInverse Of Control:控制反转)和 AOP(Aspect Oriented Programming:面向切面编程)为内核。
在java三层架构当中分别提供了相应技术:
表现层(web层)      :SpringMVC 框架,servlet
业务层(service层)  :Bean管理(IOC容器,在三层都有体现) 声明式事务
持久层(dao层)      :JdbcTemplate模板对象以及提供了ORM模块整合其他优秀的持久层技术

spring 框架: 
分层一站式框架  轻量   开源 
AOP IOC

1.2 发展历程

1997 年, IBM提出了EJB 的思想
1998 年,SUN制定开发标准规范 EJB1.0
1999 年,EJB1.1 发布
2001 年,EJB2.0 发布
2003 年,EJB2.1 发布
2006 年,EJB3.0 发布

Rod JohnsonSpring 之父)
Expert One-to-One J2EE Design and Development(2002)
阐述了 J2EE 使用EJB 开发设计的优点及解决方案
Expert One-to-One J2EE Development without EJB(2004)
阐述了 J2EE 开发不使用 EJB的解决方式(Spring 雏形)

20179 月份发布了 Spring 的最新版本 Spring5.0 通用版(GA)

1.3 优势

1. 方便解耦,简化开发:Spring 就是一个大工厂,可以管理所有对象的创建和依赖关系维护,交给Spring管理
2. AOP 编程的支持:可以方便的实现对程序进行权限拦截,日志记录,运行的监控
3. 声明式事务的支持:通过配置方式完成对事务的管理,无需手动编程
4. 方便程序的测试:对Junit支持,可以通过注解方便的对Spring程序进行测试
5. 整合外部优秀技术:Spring内部提供了对各种优秀框架(HibernateMybatisQuartz等)的直接支持
6. javaEE技术的封装 :Spring对javaEE开发当中复杂难用的API(JavaEmail, RMI等)进行封装,降低了这些API的使用难度。

1.4 体系结构

  Spring的核心是容器(IOC):  Beans Core Context SpEL表达式
  中间层技术:AOP Aspects AOP
  web: servler  springmvc 
  data Access: 数据访问层: jdbc  ORM 整合外部的优秀框架 Transaction 事务
  基于Test测试: spring 整合junit junit4.X 
  
  官方网站: 
  https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#spring-core

在这里插入图片描述

第2节:程序的耦合和解耦合

2.1 什么是程序的耦合

话术:
程序的耦合是程序之间的关联性,也就是多个类的联系是否紧密,多个对象之间的关系是否密切。

耦合度高: 
(1)不利于扩展
(2)不利于程序的维护。

生活中的案例: 
你的房子里面有窗子,那么房子和窗子就有了关联

	耦合度是松还是紧就看你的关联是强还是弱,也就是修改的代价,比如你窗子是扣死在墙里的那么你修改窗子就必须修改墙 这就比较紧密了,反应在程序上就是耦合度高,不利于程序的扩展和维护。
	但是如果你窗子是按照某种规格的 可以自由拆装的,那么修改的代价就小,耦合度也就低了,反应在程序上就是耦合度低,利于程序的扩展和维护。

我们写程序的目标就是 高内聚 低耦合!
这样修改起来 就不会有太多的联系,不用改一个地方其他的都要修改。

2.2 解决程序耦合的思路

2.2.1 编译不依赖,运行时才依赖
当我们讲解jdbc时,是通过反射来注册驱动的,代码如下:
Class.forName("com.mysql.jdbc.Driver");//使用的驱动类是指定了一个字符串
底层: DriverManager.regist(new com.mysql.jdbc.Driver());
Connection connection = DriverManager.getConnection("","","");
 	此时的好处式,我们的类中在编译阶段不再需要具体的驱动类,就算删除mysql的驱动jar包,依然可以通过编译。在运行阶段才会依赖驱动包。实际开发当中,我们应该做到编译不依赖,运行时才依赖。
  上述代码产生的新问题,mysql驱动类的全限定类名作为一个字符串java类中是写死的,一旦发生改变,还需要修改源码。

  使用配置文件结合反射就可以解决上述问题。      
2.2.2 使用工厂模式解耦合
 在实际开发中我们可以把三层的对象都使用配置文件配置起来,当启动服务器应用加载的时候,让一个类中的 方法通过读取配置文件,把这些对象创建出来并存起来。在接下来的使用的时候,直接拿过来用就好了。 

那么,这个读取配置文件,创建和获取三层对象的类就是工厂。

service 调用dao:  

原生:  new xxxDaoImpl();  问题: service实现类当中出现了 new关键字, 出现了dao 层具体的实现类。 不满足java设计原则: 面向接口开发~  总结: 耦合度高~ 

工厂模式: XXXFactory.getInstance(); 获得接口的实现类: xxxDao接口接收~  解决了: new关键字, 业务层的实现类当中, 不在出现dao层的实现类。  总结: 松耦合~ 

第3节:IOC 机制

3.1 IOC的简介

SpringIOC:IOC 是 Inversion of Control 的缩写,多数书籍翻译成“控制反转”,还有些书籍翻译成为“控制反向”或者“控制倒置”。

就是将对象的创建和维护的权利交给spring 框架。 

1996 年,Michael Mattson 在一篇有关探讨面向对象框架的文章中,首先提出了 IOC 这个概念。简单来说就是把复杂系统分解成相互合作的对象,这些对象类通过封装以后,内部实现对外部是透明的,从而降低了解决问题的复杂度,而且可以灵活地被重用和扩展。

IOC 理论提出的观点大体是这样的:借助于“第三方”实现具有依赖关系的对象之间的解耦 如下图

在这里插入图片描述

		大家看到了吧,由于引进了中间位置的“第三方”,也就是IOC容器,使得ABCD4个对象没有了耦合关系,齿轮之间的传动全部依靠“第三方”了, 全部对象的控制权全部上缴给“第三方”IOC容器,所以,IOC容器成了整个系统的关键核心,它起到了一种类似“粘合剂”的作用,把系统中的所有对象粘合 在一起发挥作用,如果没有这个“粘合剂”,对象与对象之间会彼此失去联系,这就是有人把IOC容器比喻成“粘合剂”的由来。
我们再来做个试验:把上图中间的IOC容器拿掉,然后再来看看这套系统:

在这里插入图片描述

		我们现在看到的画面,就是我们要实现整个系统所需要完成的全部内容。这时候,ABCD4个对象之间已经没有了耦合关系,彼此毫无联系,这样的话, 当你在实现A的时候,根本无须再去考虑BCD了,对象之间的依赖关系已经降低到了最低程度。所以,如果真能实现IOC容器,对于系统开发而言,这将是 一件多么美好的事情,参与开发的每一成员只要实现自己的类就可以了,跟别人没有任何关系!

总结: 
	IOC容器就是创建对象, 并且维护对象和对象之间的关联关系。

3.2 IOC作用

		IOC本质上就是一个大工厂,大容器。主要作用就是创建和管理对象的依赖关系,削减计算机程序的耦合(解除我们代码中的依赖关系),提高程序的可扩展性和可维护性。

3.3 IOC入门

3.3.1 构建工程添加依赖
<properties>
        <spring.version>5.2.5.RELEASE</spring.version>
    </properties>
    <!--导入spring的context坐标,context依赖core、beans、expression aop-->
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
    </dependencies>
3.3.2 创建持久层接口和实现类
public interface UserDao {    
    public void save();
}

public class UserDaoImpl implements UserDao {
    @Override
    public void save() {
        System.out.println("userDao save method running...... ");
    }
}

3.3.3 创建业务层接口和实现类
public interface UserService {    
    public void saveService();
}

public class UserServiceImpl implements UserService {
    @Override
    public void saveService() {
        System.out.println("userSerivce save method running......");
    }
}

3.3.4 创建IOC配置文件
xml文件名称: 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"       xsi:schemaLocation="http://www.springframework.org/schema/beans                                               http://www.springframework.org/schema/beans/spring-beans.xsd">

</beans>
3.3.5 配置文件管理对象
<?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">

    <!--配置userDaoImpl-->
    <bean id="userDao" class="com.ujiuye.dao.impl.UserDaoImpl"></bean>
    <!--配置userServiceImpl-->
    <bean id="userService" class="com.ujiuye.service.UserServiceImpl"></bean>
</beans>
3.3.6 测试
    @Test
    public void test1(){
        //1:获得spring IOC容器对象:
        ApplicationContext applicationContext =
                new ClassPathXmlApplicationContext("applicationContext.xml");
        //2:从容器当中根据id获得UserDaoImpl 对象,执行userDao对象的save方法
        UserDao userDao = (UserDao) applicationContext.getBean("userDao");
        userDao.save();
        //3:从容器当中根据id获得UserServiceImpl 对象,执行userService对象的saveService方法
        UserService userService = (UserService)applicationContext.getBean("userService");
        userService.saveService();
    }

运行结果: 

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zu3nHWrz-1666881307897)(.\images\运行结果1.png)]

第4节:基于XML的IOC

4.1 IOC配置文件详解

bean标签: 用于配置对象交给Spring 来创建。
默认情况下他会调用类中无参数的构造器,如果没有无参数构造器则不能成功创建 
基本属性: 
id      :  Bean实例对象在Spring容器当中的唯一标识
class   :  Bean的全限定类名
name    :  了解,给对象命名操作

4.2 源码解析

4.2.1 IOC容器解析(面试题目)
IOC思想基于IOC容器完成,IOC容器底层就是对象工厂,Spring 中工厂的类结构图如下:

在这里插入图片描述

1. BeanFactory :该接口是顶层接口, IOC容器的基本实现,是Spring内部使用的接口,不提供开发人员使用,加载配置文件时,不会创建对象,在获得(使用)对象时才采取创建对象。对象的创建时机,getBean()创建【稍后演示】

2. HierarchicalBeanFactory:这个工厂接口非常简单,实现了Bean工厂的分层。 工厂接口也是继承自BeanFacotory,也是一个二级接口,相对于父接口,它只扩展了一个重要的功能——工厂分层

3. AutowireCapableBeanFactory:该接口有自动装配能力,需要注意的是,ApplicationContext接口并没有实现此接口,因为应用代码很少用到此功能,如果确实需要的话,可以调用ApplicationContext的getAutowireCapableBeanFactory方法,来获取此接口的实例。 

4. ListableBeanFactory:获取bean时,Spring 鼓励使用这个接口定义的api,如查看Bean的个数、获取某一类型Bean的配置名、查看容器中是否包括某一Bean等方法。

5. ApplicationContextBeanFactory接口的子接口,提供更多强大的功能,一般由开发人员使用.接口提供了bean基础性操作同时,扩展了国际化等功能。ApplicationContext接口在加载配置文件时候就会配置文件当中的对象进行创建,存放在IOC容器当中

6. AnnotationConfigApplicationContext:   
   当使用注解配置容器对象时,需要使用此类来创建 spring 容器。它用来读取注解。

7. ClassPathXmlApplicationContext: 
   它是从类的根路径下加载配置文件 推荐使用这种

8. FileSystemXmlApplicationContext: 
   它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。
重点掌握: BeanFactory ApplicationContext

面试题目:  BeanFactory & ApplicationContext 联系和区别: 

BeanFactory : 顶层接口, 接口当中实现了基础性的功能。 提供给框架设计者使用。 

                             加载配置文件的时候, 对象不创建。 getBean();才会创建对象。 

ApplicationContext :是BeanFactory 接口的子接口。 提供了基础性功能之外, 功能进行了扩展,开发者使用。

                              加载配置文件的时候, 对象就创建成功, 并且存放在IOC 容器当中。 

ClassPathXmlApplicationContext: 从类路径下获得资源文件。 

AnnotationConfigApplicationContext: 基于主机模式使用的实现类。 

第5节:手动实现自己的IOC容器

5.1 分析IOC 实现思路

思路:
 1、创建工厂对象,加载Spring核心配置文件
 2、使用xml解析技术,获得bean标签当中id属性以及class属性对应的值
 3、底层使用反射技术,创建对象
 4、准备临时容器,存放创建的对象
 5、提供getBean方法,对外提供对象
 6、测试自定义的工厂对象

在这里插入图片描述

5.2 设计接口、类和配置文件

//设定UserDao接口
public interface UserDao {
    public void save();
}
//设定UserDao接口实现类
public class UserDaoImpl implements UserDao {
    @Override
    public void save() {
        System.out.println("userDao save method running...... ");
    }
}

5.3 配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans>
    <bean id="userDao" class="com.offcn.dao.impl.UserDaoImpl"></bean>
    <bean id="userService" class="com.offcn.service.impl.UserServiceImpl"></bean>
</beans>

5.4 解析配置文件

dom4J, jdom sax jaxp 解析器
<!--引入dom4J-->
<dependency>
    <groupId>dom4j</groupId>
    <artifactId>dom4j</artifactId>
    <version>1.6.1</version>
</dependency>
/**
 * 创建自己的工厂类
 */
public class MyBeanFactory {

    //创建一个map集合,模拟IOC容器
    private static Map<String,Object> map = new HashMap<>();

    static{
        try {
            //使用dom4J 解析xml文件:
            //第一步:获得一个解析器:
            SAXReader reader = new SAXReader();
            //第二: 读取外部的配置文件:
            String path = "src/main/resources/myApplicationContext.xml";
            //第三: 读取了整个文档对象
            Document document = reader.read(path);
            //第四: 获得根节点:
            Element rootElement = document.getRootElement();//beans
            //第五: 获得根节点下的所有的bean 标签对应的节点:
            List<Element> bean = rootElement.elements("bean");// bean
            for (Element element : bean) {
                //获得id属性对应的值:
                String id1 = element.attributeValue("id");
                //获得class属性对应的值:【全限定类名】
                String aClass = element.attributeValue("class");//获得class对应的值: 全限定类名。
                //通过反射创建对象:
                Class  clz = Class.forName(aClass);
                Object object = clz.newInstance();
                //存容器 id做key,创建出来的对象value
                map.put(id1,object);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 根据id从容器当中获得对象
     * @param id id的名称
     * @return 返回Object类型对象
     */
    public static Object getBean(String id){
        Object o = map.get(id);
        return o;
    }

}

总结: IOC容器自定义时候; 
xml解析技术: 
反射技术
工厂模式

5.5 测试

@Test
public void testMyFactory(){
    //1:创建工厂对象
    MyBeanFactory factory =new MyBeanFactory();
    //2:从容器当中根据id获得对象
    UserDao userDao = (UserDao) factory.getBean("userDao");
    System.out.println(userDao);
    userDao.save();
}
运行结果: 

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xHx59dsX-1666881307900)(./images/运行结果2.png)]

第6节:管理bean细节

6.1 bean实例化介绍

bean 对象创建~ 

6.2 bean实例化方式【面试问题】

6.2.1 构造方法的方式
它会根据默认无参构造函数来创建类对象。如果 bean 中没有默认无参构造函数,将会创建失败
(1)创建User类
public class User implements Serializable {
    public User(){
        System.out.println("user created...");
    }
}
(2)配置容器管理对象
<!--配置user对象-->
<bean id="user" class="com.ujiuye.pojo.User"></bean>
(3)测试实例化对象
    @Test
    public void testUser(){
        ApplicationContext context =
                new ClassPathXmlApplicationContext("applicationContext.xml");
        User user = (User) context.getBean("user");
        System.out.println(user);
    }
6.2.2 静态工厂方式
(1)创建静态工厂
public class ItemFactory {

    //静态方法返回实例bean
    public static User createUser(){
        System.out.println("static method running create bean ......");
        return new User();
    }
}
(2)配置容器管理对象
<!--静态工厂实例化对象:
   工厂方法的返回值存放在IOC容器当中
-->
<bean id="user" class="com.ujiuye.factory.ItemFactory" factory-method="createUser"></bean>
(3)测试实例化对象
    @Test
    public void testItemFactory(){
        ApplicationContext context =
                new ClassPathXmlApplicationContext("applicationContext.xml");
        User user = (User) context.getBean("user");
        System.out.println(user);
    }
6.2.3 实例工厂方式
(1)创建实例工厂
public class NewItemFactory {
    //工厂的非静态方法返回bean实例
    public User createUser(){
        System.out.println("Dynamic method running create bean ......");
        return new User();
    }
}
(2)配置容器管理对象
<!--实例工厂:
   步骤一; 创建对象
   步骤二: 通过对象调用方法,方法的返回值存在IOC容器当中。 
-->
 <bean id="itemFactory" class="com.ujiuye.factory.NewItemFactory"></bean>
 <bean id="user" factory-bean="itemFactory" factory-method="createUser"></bean>
(3)测试实例化对象
    @Test
    public void testNewItemFactory(){
        ApplicationContext context =
                new ClassPathXmlApplicationContext("applicationContext.xml");
        User user = (User) context.getBean("user");
        System.out.println(user);
    }

6.3 bean作用域【面试问题】

6.3.1 bean作用域介绍

所谓Bean的作用域其实就是指Spring给我们创建出的对象的存活范围,在配置文件中通过bean的scope属性指定
<bean id="" class="" scope="">
scope:指对象的作用范围,取值如下: 

取值范围说明
singleton默认值,单例的
prototype多例的
requestWEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 request 域中
sessionWEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 session 域中
global sessionWEB 项目中,应用在 Portlet 环境,如果没有 Portlet 环境那么globalSession 相当于 session
6.3.2 bean作用域的解析
(1)scope取值为singleton
 Bean的实例化个数:1Bean的实例化时机:当Spring核心文件被加载时,实例化配置的Bean实例
(2)scope取值为prototype
 Bean的实例化个数:多个
 Bean的实例化时机:当调用getBean()方法时实例化Bean 
注意: 多例对象,不会随容器而创建, 不会随容器销毁而销毁。 
	在内存当中, 由垃圾回收器定期回收~
(3)Scope取值为其他值
scope指定为其他值,需要在特定的环境下使用, 只需要作为一个了解知识,面试能够回答出来即可

6.4 bean的生命周期

6.4.1 bean生命周期介绍
在这里所谓的Bean的生命周期其实指的是Bean创建到销毁的这么一段时间。 
在Spring中可以通过配置的形式,指定bean在创建后和销毁前要调用的方法。
属性:
init-method:指定bean在创建后调用的方法
destroy-method:对象在销毁前调用的方法
<bean id="xxx" class="xxx" init-method="" destroy-method=""></bean>
6.4.2 单例对象的生命周期
(1)添加方法init和destory
public class UserServiceImpl implements UserService {
    public void init(){
        System.out.println("init method running...");
    }
    @Override
    public void saveService() {
        System.out.println("userSerivce save method running......");
    }

    public void destroy(){
        System.out.println("destroy method running...");
    }
}
(2)配置文件中配置UserService
<!--配置userServiceImpl-->
<bean id="userService" class="com.ujiuye.service.UserServiceImpl" init-method="init" destroy-method="destroy">
    
</bean>
(3)测试单例对象生命周期
@Test
    public void test1(){
        ClassPathXmlApplicationContext applicationContext =
                new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = (UserService) applicationContext.getBean("userService");
        userService.saveService();
        //关闭工厂:
        applicationContext.close();
    }
单例对象总结: 

对象创建:当应用加载,创建容器时,对象就被创建了

对象运行:只要容器在,对象一直活着

对象销毁:当应用卸载,销毁容器时,对象就被销毁了

6.4.3 多例对象的生命周周期
(1)配置文件scope属性
 <!--配置userServiceImpl-->
 <bean id="userService" class="com.ujiuye.service.UserServiceImpl" init-method="init" destroy-method="destroy" scope="prototype"></bean>
(2)测试多例对象生命周期
@Test
public void test1(){
    ClassPathXmlApplicationContext applicationContext =
        new ClassPathXmlApplicationContext("applicationContext.xml");
    UserService userService = (UserService) applicationContext.getBean("userService");
    userService.saveService();
    //关闭工厂:
    applicationContext.close();
}
多例对象总结: 

对象创建:当使用对象时(getBean),创建新的对象实例

对象运行:只要对象在使用中,就一直活着

对象销毁:当对象长时间不用时,被 Java 的垃圾回收器回收了, 对destroy-method属性针对多例不生效。

第7节:依赖注入

7.1 介绍


依赖注入(Dependency Injection):简称DI,它是 Spring 框架核心 IOC 的具体实现。
在编写程序时,通过控制反转,把对象的创建交给了 Spring,但是代码中不可能出现没有依赖的情况。
IOC 解耦只是降低他们的依赖关系,但不会消除。
例如:业务层仍会调用持久层的方法。
那这种业务层和持久层的依赖关系,在使用 Spring 之后,就让 Spring 来维护了。
简单的说,就是坐等框架把持久层对象传入业务层,而不用我们自己去获取

简单理解: 依赖注入就是spring IOC 容器在创建对象的时候, 给属性赋值。 

7.2 依赖注入方式

7.2.1 构造函数注入
(1)创建实体类
	顾名思义,就是使用类中的构造函数,给成员变量赋值。注意,赋值的操作不是我们自己做的,而是通过配置
的方式,让 Spring 框架来为我们注入。具体代码如下
public class Account {
    private String name;
    private Integer age;
    private Date birthday;

    public Account(String name, Integer age, Date birthday) {
        this.name = name;
        this.age = age;
        this.birthday = birthday;
    }
}
(2)配置文件管理类
<!--使用构造函数的方式:给account中的属性赋值
        要求:
            类中需要提供一个对应参数列表的构造器函数
        涉及的标签:
            constructor-arg:
             属性:
             name: 执行参数在构造器中的名称
             value:它能赋的值是基本数据类型和 String 类型
             ref:它能赋的值是其他 bean 类型,也就是说,必须得是在配置文件中配置过的 bean
    -->
<bean id="now" class="java.util.Date"></bean>
<bean id="account" class="com.ujiuye.pojo.Account">
    <constructor-arg name="name" value="王达"></constructor-arg>
    <constructor-arg name="age" value="20"></constructor-arg>
    <constructor-arg name="birthday" ref="now"></constructor-arg>
</bean>
(3)构造函数注入测试
@Test
public void testDI(){
    ClassPathXmlApplicationContext applicationContext =
        new ClassPathXmlApplicationContext("applicationContext.xml");
    Account account = (Account) applicationContext.getBean("account");
    System.out.println("name:"+account.getName()+" age:"+account.getAge()+" birthday:"+account.getBirthday());
    //打印结果: name:王达 age:20 birthday:Thu Feb 04 13:53:45 CST 2021
}
7.2.2 setter注入
(1)修改类添加setter方法
顾名思义,就是在类中提供需要注入成员的 set 方法。具体代码如下:
public class Account {
    private String name;
    private Integer age;
    private Date birthday;
    
    public Account() {
    }

    public Account(String name, Integer age, Date birthday) {
        this.name = name;
        this.age = age;
        this.birthday = birthday;
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
}
(2)注入依赖数据
<!--使用set方法的方式给属性赋值
        涉及的标签:
            property
            属性:
               name:找的是类中set方法后面的部分
               ref: 给属性赋值是其他bean类型的
               value:给属性赋值是基本数据类型和 string 类型的
             实际开发当中, 此种方式用的比较多,推荐使用
           -->
<bean id="now" class="java.util.Date"></bean>
<bean id="account" class="com.ujiuye.pojo.Account">
    <property name="name" value="张三丰"></property>
    <property name="age" value="31"></property>
    <property name="birthday" ref="now"></property>
</bean>
(3)setter注入测试方法
@Test
public void testDI(){
    ClassPathXmlApplicationContext applicationContext =
        new ClassPathXmlApplicationContext("applicationContext.xml");
    Account account = (Account) applicationContext.getBean("account");
    System.out.println("name:"+account.getName()+" age:"+account.getAge()+" birthday:"+account.getBirthday());
    //测试结果: name:张三丰 age:31 birthday:Thu Feb 04 14:05:19 CST 2021
}
 
7.2.3 P名称空间注入
语法: p:属性名称=“”  
在xml当中引入p名称空间
xmlns:p="http://www.springframework.org/schema/p"

语法: 
<bean id="account" class="com.offcn.pojo.Account" p:name="唐晓飞" p:age="21" p:birthday-ref="birthday"></bean>

7.2.4 SPEL 表达式注入
<!--SPEL注入: spring el expression
       (1)  底层是调用了set方法
       (2)  #{} spring EL 语法
       (3)  不管是普通属性或者是对象属性, 都使用value 赋值。
       (4)功能最强大 , 属性赋值的时候,可以调用对象的属性, 可以调用对象的方法。

     -->
    <bean id="account" class="com.offcn.pojo.Account">
        <property name="name" value="#{'admin'}"></property>
        <property name="age" value="#{account.calcullatorAge()}"></property>
        <property name="birthday" value="#{birthday}"></property>
    </bean>

7.3 注入集合数据

7.3.1 添加集合属性
顾名思义,就是给类中的集合成员传值,它用的也是set方法注入的方式,只不过变量的数据类型都是集合。 
我们这里介绍注入数组,List,Set,Map,Properties。具体代码如下:

public class Account {
    //注入数组,List集合,Set集合,Map集合,Properties集合属性
    private String[] myStrs;
    private List<String> myList;
    private Set<String> mySet;
    private Map<String,String> myMap;
    private Properties myProps;

    public Account() {
    }

    public String[] getMyStrs() {
        return myStrs;
    }

    public void setMyStrs(String[] myStrs) {
        this.myStrs = myStrs;
    }

    public List<String> getMyList() {
        return myList;
    }

    public void setMyList(List<String> myList) {
        this.myList = myList;
    }

    public Set<String> getMySet() {
        return mySet;
    }

    public void setMySet(Set<String> mySet) {
        this.mySet = mySet;
    }

    public Map<String, String> getMyMap() {
        return myMap;
    }

    public void setMyMap(Map<String, String> myMap) {
        this.myMap = myMap;
    }

    public Properties getMyProps() {
        return myProps;
    }

    public void setMyProps(Properties myProps) {
        this.myProps = myProps;
    }
}
7.3.2 注入依赖集合数据
<!--注入集合类型数据:
        涉及到标签:
         List结构: array list set
         Map结构:  map entry props prop
    -->
<bean id="account" class="com.ujiuye.pojo.Account">
    <!--注意:在注入集合数据时,只要是结构相同,标签可以互换-->

    <!--注入数组数据-->
    <property name="myStrs">
        <array>
            <value>array-AAA</value>
            <value>array-BBB</value>
            <value>array-CCC</value>
        </array>
    </property>
    <!--注入List集合数据-->
    <property name="myList">
        <list>
            <value>list-AAA</value>
            <value>list-BBB</value>
            <value>list-CCC</value>
        </list>
    </property>
    <!--注入Set集合数据-->
    <property name="mySet">
        <list>
            <value>set-AAA</value>
            <value>set-BBB</value>
            <value>set-CCC</value>
        </list>
    </property>
    <!--注入Map集合-->
    <property name="myMap">
        <map>
            <entry key="map-a" value="AAA"></entry>
            <entry key="map-b">
                <value>BBB</value>
            </entry>
        </map>
    </property>

    <!--注入Properties集合-->
    <property name="myProps">
        <props>
            <prop key="pro-a">AAA</prop>
            <prop key="pro-b">BBB</prop>
        </props>
    </property>
</bean>
7.3.3 集合注入测试方法
@Test
public void testDI(){
    ClassPathXmlApplicationContext applicationContext =
        new ClassPathXmlApplicationContext("applicationContext.xml");
    Account account = (Account) applicationContext.getBean("account");
    System.out.println("array:"+ Arrays.toString(account.getMyStrs()));
    System.out.println("list:"+account.getMyList());
    System.out.println("set:"+account.getMySet());
    System.out.println("map:"+account.getMyMap());
    System.out.println("props:"+account.getMyProps());
        /*
        测试结果: 
        array:[array-AAA, array-BBB, array-CCC]
        list:[list-AAA, list-BBB, list-CCC]
        set:[set-AAA, set-BBB, set-CCC]
        map:{map-a=AAA, map-b=BBB}
        props:{pro-b=BBB, pro-a=AAA}

         */
}

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

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

相关文章

力扣刷题day32|738单调递增的数字、714买卖股票的最佳时机含手续费、968监控二叉树

文章目录738. 单调递增的数字思路难点&#xff1a;遍历顺序难点&#xff1a;设置flag714. 买卖股票的最佳时机含手续费贪心思路难点968. 监控二叉树思路难点&#xff1a;如何隔两个节点放一个摄像头738. 单调递增的数字 力扣题目链接 当且仅当每个相邻位数上的数字 x 和 y 满…

常用算法———P I D控制算法(P I D三个参数的作用和两种P I D算法的代码实现)

如果有错误请及时指出&#xff0c;大家一起学习交流。 目录 一、PID的概述 二、PID三个参数的控制原理 1、P控制器 2、I控制器 3、D控制器 4、PID控制器 5、PID的数学公式 三、位置式PID和增量式PID的差别和代码实现 1、位置式PID和增量式PID的差别 2、位置式PID …

(附源码)计算机毕业设计SSM竞赛报名管理系统

&#xff08;附源码&#xff09;计算机毕业设计SSM竞赛报名管理系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&…

mindspore实现自定义CNN图像分类模型

一、数据集定义 使用mindspore.dataset中的ImageFolderDataset接口加载图像分类数据集&#xff0c;ImageFolderDataset接口传入数据集文件上层目录&#xff0c;每个子目录分别放入不同类别的图像。使用python定义一个create_dataset函数用于创建数据集&#xff0c;在函数中使用…

[C++基础]-初识模板

前言 作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正。 目录 一、泛型编…

【正点原子STM32连载】第五十五章 T9拼音输入法实验 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1

1&#xff09;实验平台&#xff1a;正点原子MiniPro H750开发板 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id677017430560 3&#xff09;全套实验源码手册视频下载地址&#xff1a;http://www.openedv.com/thread-336836-1-1.html 4&#xff…

deepwalknode2vec 代码实战

提示&#xff1a;笔记内容来自于B站up主同济子豪兄 文章目录1. Embedding嵌入的艺术2. deepwalk2.1. 什么是图嵌入&#xff1f;2.2. deepwalk的步骤1、生成graph&#xff1b;2、利用random walk生成多个路径&#xff1b;3、训练表示向量的学习&#xff1b;4、为了解决分类个数过…

航拍遥感数据集

一、Roundabout Aerial Images for Vehicle Detection 本数据集是从无人机拍摄的西班牙环形交叉口航空图像数据集&#xff0c;使用PASCAL VOC XML文件进行注释&#xff0c;指出车辆在其中的位置。此外&#xff0c;还附带一个CSV文件&#xff0c;其中包含与捕获的环形交叉口的位…

深度学习 神经网络(2)前向传播

深度学习 神经网络&#xff08;2&#xff09;前向传播一、前言二、神经网络结构三、前向传播四、参考资料一、前言 前面介绍了《感知器》&#xff0c;类似于单个神经元细胞&#xff0c;现在我们用多个感知器组合成更加复杂的神经网络。本文介绍了多层神经网络通过前向传播方法…

超市营业额数据分析

文章目录1&#xff1a;查看单日交易额最小的3天的交易数据&#xff0c;并查看这3天是周几1.1&#xff1a;导入模块1.2&#xff1a;数据处理1.3&#xff1a;输出结果完整代码2&#xff1a;把所有员工的工号前面增加一位数字&#xff0c;增加的数字和原工号最后一位相同&#xff…

FBAR滤波器的工作原理及制备方法

近年来&#xff0c;随着无线通信技术朝着高频率和高速度方向迅猛发展&#xff0c;以及电子元器件朝着微型化和低功耗的方向发展&#xff0c;基于薄膜体声波谐振器&#xff08;Film Bulk Acoustic Resonator&#xff0c;FBAR&#xff09;的滤波器的研究与开发越来越受到人们的关…

酒楼拓客营销流程,酒楼宣传推广方案

随著网络时代的发展&#xff0c;许多行业受到了大大的冲击&#xff0c;其中也涵盖酒楼&#xff0c;在目前的情况下&#xff0c;对于酒楼来说&#xff0c;无论是互联网还是线下&#xff0c;引流都是最重要的。那么酒楼如何做好营销推广工作&#xff0c;从而提升业绩&#xff1f;…

乘风而起!企业级应用软件市场迅猛发展,有哪些机会可以把握?

数字化转型战略的深入&#xff0c;使我国企业级软件市场得到了迅速的发展&#xff0c;据统计&#xff0c;2021年我国企业级应用软件市场规模超过了600亿元&#xff0c;其中商业智能&#xff08;BI&#xff09;市场规模超过了50亿元。 得益于中国企业对于数据系统的本地化部署需…

Hadoop3 - MapReduce DB 操作

一、MapReduce DB 操作 对于本专栏的前面几篇文章的操作&#xff0c;基本都是读取本地或 HDFS 中的文件&#xff0c;如果有的数据是存在 DB 中的我们要怎么处理呢&#xff1f; Hadoop 为我们提供了 DBInputFormat 和 DBOutputFormat 两个类。顾名思义 DBInputFormat 负责从数…

MODBUS通信浮点数存储解析常用算法

MODBUS通信相关的基础知识,各种PLC通信程序的写法。可以参看专栏的其它文章这里不赘述。MODBUS通信时,数据帧都是以字节为单位发送和接收的,接收到的字节,如何存放和解析。就需要我们具备数据处理类的知识了,这里需要大家简单了解下有关数据结构的基础知识,这方面比较薄弱…

AcWing 蓝桥杯AB组辅导课 05、树状数组与线段树

文章目录前言一、树状数组1.1、树状数组知识点1.2、树状数组代码模板模板题&#xff1a;AcWing 1264. 动态求连续区间和例题例题1、AcWing 1265. 数星星【中等&#xff0c;信息学奥赛一本通】习题习题1&#xff1a;1215. 小朋友排队【中等&#xff0c;蓝桥杯】二、 线段树知识点…

27.5 Java集合之Set学习(基本概念,存储原理,性能测试)

文章目录1.Set接口1.1 Set的特性是什么&#xff1f;2.具体实现2.1 HashSet2.1.1 存储原理2.1.2 性能测试2.2 TreeSet2.2.1 存储原理2.2.2 性能测试2.3 EnumSet&#xff08;了解即可&#xff09;2.3.1 存储原理2.4 LinkedHashSet2.4.1 存储原理2.4.2 性能测试2.4.3 代码地址1.Se…

【Gitee】上传本地项目到 Gitee 仓库(入门篇)

本文主要介绍上传本地项目到 Gitee 仓库的过程&#xff0c;可以说是一个比较傻瓜的教材吧&#xff0c;从0开始&#xff0c;祝大家都能一次成功~~~ 一、前期准备 1. 配置 Gitte 创建 Gitte 账号&#xff0c;绑定好邮箱&#xff0c;并创建一个空仓库 。创建账号绑定邮箱过程这部…

【信号检测】基于小波变换的信号趋势检测和分离研究附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

双十一好物推荐:2022年好用的数码好物分享

一年一度的双十一尽在眼前&#xff0c;因为双十一的优惠力度是一年中最大的一次&#xff0c;所以许多人都想着直接一年屯一次&#xff0c;一次屯一年的理念&#xff0c;那么作为资深剁手党的我来说&#xff0c;对比于选购双十一好物来说我还是比较有心得的&#xff0c;下面让我…