Spring中IOC创建对象的两种方式和创建时机

最近在学习Spring相关知识,官网文档如下
Spring Core Technologies: https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-constructor-injection.

一、创建方式

方式1:通过无参构造方法来创建

package com.zhang.pojo;

public class User {
    private String name;
    public User(){
        System.out.println("This is a no args method!");
    }

    public void show(){
        System.out.println("This is a show method!");
    }

    public String getName() {
        return name;
    }

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

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

    <bean id="User" class="com.zhang.pojo.User">
        <property name="name" value="张三丰"></property>
    </bean>

</beans>

MyTest

import com.zhang.pojo.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    @Test
    public void test1(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        User user = (User)ac.getBean("User");
        user.show();
    }
}

结果可以发现,在调用show方法之前,User对象已经通过无参构造初始化了!执行结果如下:
在这里插入图片描述
方式2:通过有参构造方法来创建
User

package com.zhang.pojo;

public class User {
    private String name;
    public User(String name){
        //System.out.println("This is a no args method!");
        this.name = name;
    }

    public void show(){
        System.out.println("This is a show method!");
    }

    public String getName() {
        return name;
    }

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

这里是官网详细配置使用方式
在这里插入图片描述
beans.xml

<!--第一种:下标赋值-->
    <bean id="user" class="com.zhang.pojo.User">
        <constructor-arg index="0" value="张三丰"></constructor-arg>
    </bean>

    <!--第二种:类型赋值。
        如果两个参数都是String类型,则没有办法使用。
        所以不建议使用第二种
     -->
    <bean id="user" class="com.zhang.pojo.User">
        <constructor-arg type="java.lang.String" value="张三丰"/>
    </bean>

    <!--第三种:直接通过参数名实现-->
    <bean id="user" class="com.zhang.pojo.User">
        <constructor-arg name="name" value="张三丰"></constructor-arg>
    </bean>

二、什么时候创建对象?

创建时机
1:默认的在Spring容器启动的时候
2:在getBean的时候创建对象(就是拿到配置文件中的标识符的时候创建对象)

在Spring的配置文件bean中有一个属性lazy-init=“default/true/false”
(1)如果lazy-init为"default/false"在启动spring容器时创建对象
(2)如果lazy-init为"true",在context.getBean时才要创建对象

意义
(1)在启动spring容器的时候,检查spring容器配置文件的正确性,如果spring容器不能正常启动,整个tomcat就不能正常启动。但是这样的缺点是把一些bean过早的放在了内存中,如果有数据,则对内存来是一个消耗,但是可以过早发现错误。
(2)getBean时创建对象可以减少内存的消耗,但是不容易发现错误。

注意
如果一个bean的scope属性为scope="pototype"时,即使设置了lazy-init=“false”,容器启动时不实例化bean,而是调用getBean方法是实例化的。

三、IOC容器创建对象过程

(1)先通过createBeanFactory创建出一个bean工厂(利用顶级接口BeanFactory下的DefaultListableBeanFactory接口)。
(2)循环创建对象,由于容器中bean默认都是单例,则优先通过getBean,doGetBean从容器中查找。
(3)如果找不到则通过createBean,doCreateBean方法,以反射形式创建对象。一般情况下使用的是无参构造方法(getDeclaredConstructor,newInscance)。
(4)进行对象的属性填充(populateBean)。
(5)进行其它初始化操作(initializingBean)。

参考文章
https://blog.csdn.net/z19950712/article/details/112335806

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是代码实现: 1. 编写视图层JSP代码,页面提供表单 ```jsp <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>新增图书</title> </head> <body> <h2>新增图书</h2> <form action="addBook" method="post"> <label>图书名称:</label> <input type="text" name="bookName" required><br> <label>出版社:</label> <input type="text" name="press" required><br> <label>出版日期:</label> <input type="date" name="pressDate" required><br> <label>作者:</label> <input type="text" name="author" required><br> <label>定价:</label> <input type="number" name="price" required><br> <label>ISBN:</label> <input type="text" name="ISBN" required><br> <input type="submit" value="提交"> </form> </body> </html> ``` 2. 编写控制层Java代码,获取视图层提交的表单请求,控制方法注入表单项参数,控制层完成JavaBean封装和业务层代码调用。 ```java @Controller public class BookController { @Autowired private BookService bookService; @RequestMapping("/addBook") public ModelAndView addBook(@RequestParam("bookName") String bookName, @RequestParam("press") String press, @RequestParam("pressDate") Date pressDate, @RequestParam("author") String author, @RequestParam("price") BigDecimal price, @RequestParam("ISBN") String ISBN) { Book book = new Book(); book.setBookName(bookName); book.setPress(press); book.setPressDate(pressDate); book.setAuthor(author); book.setPrice(price); book.setISBN(ISBN); String result = bookService.addBook(book); ModelAndView modelAndView = new ModelAndView(); if(result == null) { modelAndView.setViewName("add_result"); modelAndView.addObject("result", "添加成功"); } else { modelAndView.setViewName("add_result"); modelAndView.addObject("result", "添加失败,原因:" + result); } return modelAndView; } } ``` 3. 编写业务层Java代码,将控制层传输的JavaBean进行非空校验然后调用持久层代码。 ```java @Service public class BookService { @Autowired private BookDao bookDao; public String addBook(Book book) { if(book.getBookName() == null || book.getBookName().equals("")) { return "图书名称不能为空"; } if(book.getPress() == null || book.getPress().equals("")) { return "出版社不能为空"; } if(book.getPressDate() == null || book.getPressDate().after(new Date())) { return "出版日期不能为空且不能晚于当前时间"; } if(book.getAuthor() == null || book.getAuthor().equals("")) { return "作者不能为空"; } if(book.getPrice() == null || book.getPrice().compareTo(BigDecimal.ZERO) <= 0) { return "定价不能为空且必须大于0"; } if(book.getISBN() == null || book.getISBN().equals("")) { return "ISBN不能为空"; } try { bookDao.addBook(book); return null; } catch(Exception e) { e.printStackTrace(); return "数据库异常"; } } } ``` 4. 编写持久层Java代码,将经过控制层校验的JavaBean转换成SQL语句并向MySQL数据库Test的book表插入一条新增记录。 ```java @Repository public class BookDao { @Autowired private JdbcTemplate jdbcTemplate; public void addBook(Book book) { String sql = "insert into book(bookName, press, pressDate, author, price, ISBN) values (?, ?, ?, ?, ?, ?)"; jdbcTemplate.update(sql, book.getBookName(), book.getPress(), book.getPressDate(), book.getAuthor(), book.getPrice(), book.getISBN()); } } ``` 5. 编写视图层JSP代码,显示新增成功或者失败及失败原因。 ```jsp <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>新增结果</title> </head> <body> <h2>${result}</h2> <a href="addBookPage">返回</a> </body> </html> ``` 注意事项: 1. 页面表单不需要填写图书编号,而交给数据库自增长生成编号。 2. 持久层代码使用JDBC完成,允许使用ORM框架。 3. 必须使用SpringMVC框架,可以使用SpringIoC。 提交要求: 1. 使用eclipseForJavaEE进行开发。 2. 将代码打包成war包并上传至服务器,提供war包下载链接。 3. 提供MySQL数据库Test的book表结构及插入数据的SQL语句。 MySQL数据库Test的book表结构及插入数据的SQL语句如下: ```sql CREATE TABLE `book` ( `bookId` int(11) NOT NULL AUTO_INCREMENT COMMENT '图书编号', `bookName` varchar(30) NOT NULL COMMENT '图书名称', `press` varchar(20) NOT NULL COMMENT '出版社', `pressDate` date NOT NULL COMMENT '出版日期', `author` varchar(10) NOT NULL COMMENT '作者', `price` decimal(10,2) NOT NULL COMMENT '定价', `ISBN` char(13) NOT NULL COMMENT 'ISBN', PRIMARY KEY (`bookId`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='图书'; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值