Bean 的实例化与装配

主要程序代码块:

实验要求:
理解 Spring 的 IoC/DI 的原理,掌握 Spring 使用注解方式和编程及 Spring 的分层设计
方法。
实验 1:集合类型注入
编写 UserInfo 类,包含用户姓名(String)、性别(boolean)、年龄(int)、出生年月(Date)、个人爱好(list 集合),采用 set 注入和构造注入两种方式,实现这些属性值的注入,并在测试程序中显示所有属性的值。
实验 2:
编写工厂类(BeanFactory)、Print 类(属性:pName、pColor 等),要求利用 Spring 容器通过工厂类 BeanFactory 生成 Print 对象,并生成测试结果。
实验 3:
利用 Spring 框架,通过注解方式实现为自己的校园卡充值。
在 Dao 层建立 CardDao 类,编写充值方法,实现充值(在控制台显示充值金额,将用户充值信息保存到数据库),在 Biz 层建立 CardBiz 类,编写充值方法,调用 Dao层中的充值方法,完成充值。在 CardController 类中编写充值方法调用 CardBiz 的充值方法。在程序中,通过代码方式调用控制层充值方法,完成充值,并在控制台显示充值金额。在实现过程中不能利用 new 操作来完成类的实例化。观察@Autowired 和@Resource 进行注解时有何不同。
实验 4:
根据自己的理解,描述 Bean 的装配方式。

实验分析:

  • 实验一主要运用Bean基于XML的装配:设值注入、构造注入。
  • 实验二采用的是静态工厂实例化。
  • 实验三主要涉及到Bean的实例化与装配(基于注解的装配)、此外还涉及了Spring对于数据库的连接。此实验可参考利用Spring框架为自己的校园卡充值。

代码实现:

实验一

set注入

package com.cqust;

import java.util.Date;
import java.util.List;

public class UserInfo1 {
    private String name;
    private boolean male;
    private int age;
    private Date birth;
    private List<String> Hobby;

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

    public void setMale(boolean male) {
        this.male = male;
    }

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

    public void setBirth(Date birth) {
        this.birth = birth;
    }

    public void setHobby(List<String> hobby) {
        Hobby = hobby;
    }

    @Override
    public String toString() {
        return "UserInfo{" +
                "姓名='" + name + '\'' +
                ", 男性=" + male +
                ", 年龄=" + age +
                ", 出生日期='" + birth + '\'' +
                ", 兴趣爱好=" + Hobby +
                '}';
    }
}

配置文件

<?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="userInfo1" class="com.cqust.UserInfo1">
        <property name="name" value="Hades"></property>
        <property name="male" value="true"></property>
        <property name="age" value="20"></property>
        <property name="birth" value="2022/9/16"></property>
        <property name="hobby">
            <list>
                <value>阅读</value>
                <value>听音乐</value>
                <value>运动</value>
            </list>
        </property>
    </bean>
</beans>

构造注入

package com.cqust;

import java.util.Date;
import java.util.List;

public class UserInfo2 {
    private String name;
    private boolean male;
    private int age;
    private Date birth;
    private List<String> Hobby;

    public UserInfo2(String name, boolean male, int age, Date birth, List<String> hobby) {
        this.name = name;
        this.male = male;
        this.age = age;
        this.birth = birth;
        Hobby = hobby;
    }

    @Override
    public String toString() {
        return "UserInfo{" +
                "姓名='" + name + '\'' +
                ", 男性=" + male +
                ", 年龄=" + age +
                ", 出生日期='" + birth + '\'' +
                ", 兴趣爱好=" + Hobby +
                '}';
    }
}

配置文件

<?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="userInfo2" class="com.cqust.UserInfo2">
        <constructor-arg name="name" value="Hades"></constructor-arg>
        <constructor-arg name="male" value="true"></constructor-arg>
        <constructor-arg name="age" value="20"></constructor-arg>
        <constructor-arg name="birth" value="2022/9/16"></constructor-arg>
        <constructor-arg name="hobby">
            <list>
                <value>阅读</value>
                <value>听音乐</value>
                <value>运动</value>
            </list>
        </constructor-arg>
    </bean>
</beans>

测试文件(Test1)

import com.cqust.UserInfo1;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test1 {
    public static void main(String[] args){
        ApplicationContext applicationContext =
                new ClassPathXmlApplicationContext("applicationBean1_1.xml");	//这里展示的是setter方法,构造方法请更换applicationBean1_2.xml
        UserInfo1 userInfo1 = applicationContext.getBean("userInfo1", UserInfo1.class);	//更换为userInfo2
        System.out.println("属性setter方法注入:");	//更换为构造方法注入
        System.out.println(userInfo1);	//更换为userInfo2
    }
}

实验二

Beanfactory类

package com.cqust;

public class BeanFactory {
    public static Print createBean(){
        return new Print();
    }
}

Print类

package com.cqust;

public class Print {
    private String pName;
    private String pColor;

    public void setpName(String pName) {
        this.pName = pName;
    }

    public void setpColor(String pColor) {
        this.pColor = pColor;
    }

    @Override
    public String toString() {
        return "Print{" +
                "p名称='" + pName + '\'' +
                ", p颜色='" + pColor + '\'' +
                '}';
    }
}

配置文件

<?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="print" class="com.cqust.BeanFactory" factory-method="createBean">
        <property name="pName" value="Hades的静态工厂实例化"></property>
        <property name="pColor" value="red"></property>
    </bean>
</beans>

测试文件(Test2)

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test2 {
    public static void main(String[] args){
        ApplicationContext applicationContext =
                new ClassPathXmlApplicationContext("applicationBean2.xml");
        System.out.println(applicationContext.getBean("print"));

    }
}

实验三

DataSource类:

package com.cqust.biz;

import com.cqust.dao.CardDao;
import com.cqust.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service("cardBiz") // 注册 bean
public class CardBiz {
    // 使用注解自动注入并指定注入的 bean 的 id
    @Autowired
    private CardDao cardDao;
    public int save(User user) {
        try {
            // 执行 dao 中的方法并返回结果
            return cardDao.insert(user);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }
    public double selectMoney(String username){
        try {
            return cardDao.selectMoney(username);
        }catch (Exception e) {
            e.printStackTrace();
        }
        return -1;
    }
    public int charge(String username,double money){
        try {
            return cardDao.charge(username, cardDao.selectMoney(username)+money);
        }catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }
}

配置文件(properties)

jdbc.dirver = com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
jdbc.username=root
jdbc.password=1

User类

package com.cqust.entity;

import org.springframework.stereotype.Component;

@Component
public class User {
    private String username;
    private double money;
    public User(String username, double money) {
        this.username = username;
        this.money = money;
    }
    public String getUsername() {return username;}
    public double getMoney() {
        return money;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public void setMoney(double money) {
        this.money = money;
    }
    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", money=" + money +
                '}';
    }
}

CardDao类

package com.cqust.dao;

import com.cqust.entity.User;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.stereotype.Repository;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

@Repository("cardDao")
public class CardDao {
    private ComboPooledDataSource dataSource;
    public CardDao(ComboPooledDataSource dataSource) {
        this.dataSource = dataSource;
    }
    public int insert(User p) throws Exception {
        // 获取数据库连接并预编译 sql 语句
        PreparedStatement ps = dataSource.getConnection().prepareStatement("insert into user(username,money)values(?,?)");
        // 设置?的值
        ps.setString(1,p.getUsername());
        ps.setDouble(2,p.getMoney());
        // 执行并返回结果
        return ps.executeUpdate(); // 省略关闭资源
    }
    public double selectMoney(String username) throws SQLException {
        PreparedStatement ps = dataSource.getConnection().prepareStatement("select money from user where username=?");
        ps.setString(1,username);
        ResultSet rs= ps.executeQuery();
        while(rs.next()){
            return rs.getDouble("money");
        }
        return -1;
    }
    public int charge(String username,double money) throws SQLException {
        PreparedStatement ps = dataSource.getConnection().prepareStatement("update user set money = ? where username = ? ");
        ps.setDouble(1,money);
        ps.setString(2,username);
        return ps.executeUpdate();
    }
}

CardBiz类

package com.cqust.biz;

import com.cqust.dao.CardDao;
import com.cqust.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service("cardBiz") // 注册 bean
public class CardBiz {
    // 使用注解自动注入并指定注入的 bean 的 id
    @Autowired
    private CardDao cardDao;
    public int save(User user) {
        try {
            // 执行 dao 中的方法并返回结果
            return cardDao.insert(user);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }
    public double selectMoney(String username){
        try {
            return cardDao.selectMoney(username);
        }catch (Exception e) {
            e.printStackTrace();
        }
        return -1;
    }
    public int charge(String username,double money){
        try {
            return cardDao.charge(username, cardDao.selectMoney(username)+money);
        }catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }
}

CardController类

package com.cqust.controller;

import com.cqust.biz.CardBiz;
import com.cqust.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class CardController {
    @Autowired
    private CardBiz cardBiz;
    public void save(User user){
        double money=cardBiz.selectMoney(user.getUsername());
        int rs=0;
        if(money==-1){
            rs=cardBiz.save(user);
        }
        if (rs==0){
            System.out.println("保存失败,该用户已存在!");
        }else{
            System.out.println("保存成功");
        }
    }
    public double show(User user){
        Double money=cardBiz.selectMoney(user.getUsername());
        if (money==null){
            System.out.println("该用户不存在!");
            return 0.0;
        }
        return money;
    }
    public void charge(User user,Double money){
        int rs=cardBiz.charge(user.getUsername(),money+ user.getMoney());
        if(rs==0){
            System.out.println("该用户不存在!");
        }else{
            System.out.println("充值成功!");
        }
    }
}

测试文件(Test3)

import com.cqust.controller.CardController;
import com.cqust.dao.DataSource;
import com.cqust.entity.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Test3 {
    public static void main(String[] args) {
        //获取核心容器(IoC)对象 需要引用DataSource类
        ApplicationContext anno = new
                AnnotationConfigApplicationContext(DataSource.class);
        // 根据 bean 的 id 获取对象
        CardController cardController = anno.getBean("cardController", CardController.class);
        // 执行方法
        User user = anno.getBean("user",User.class);
        user.setUsername("Hades");
        user.setMoney(4.50);
        System.out.println(user);
        cardController.save(user);
        cardController.show(user);
        cardController.charge(user,888.88);
    }
}


实验四

Bean的装配方式:
&Bean的装配可以理解为依赖关系注入,Bean的装配方式即Bean的依赖注入的方式。

Spring容器支持多种形式的Bean的装配方式,如基于XML的装配、基于注解的装配、自动装配等。其中最常用的是基于注解的装配。

一、基于XML的装配
Spring提供了两种基于XML的装配方式:设值(setter)注入、构造注入

Spring实例化Bean的过程中,Spring首先会调用Bean的默认构造方法来实例化Bean对象,然后通过反射的方式调用setter方法来注入属性值。

设值(setter)注入

  • Bean类必须提供一个默认的无参构造方法
  • Bean类必须为需要注入的属性提供对应的setter方法
  • 在配置文件中,需要使用 元素为每个属性注入值

构造注入

  • Bean类必须提供有参构造方法
  • 在配置文件中,需要使用元素来定义构造方法的参数,也可以使用其value属性来设置该参数的值

二、基于注解的装配
Spring中定义了一系列的注解,常用的注解如下:

  • @Component:描述Spring中的Bean,可以作用在任何层次

  • @Repository:用于将持久层(Dao层)的类标识为Spring中的Bean

  • @Service:用于将业务层(Service层)的类标识为Spring中的Bean

  • @Controller:用于将控制层(Controller层)的类标识为Spring中的Bean

  • @Autowired:用于对Bean的属性变量、属性的setter方法以及构造方法进行标注,配合对应的注解处理器完成Bean的自动装配工作。默认按照Bean的类型进行装配

  • @Resource:其作用与@Autowired一样。其区别在于@Autowired默认Bean的类型装配,而@Resource默认按照Bean的实例名称进行装配

@Resource中有两个重要属性:name和type。Spring将name属性解析为Bean实例名称,type属性解析为Bean实例类型。如果指定name属性,则按实例名称进行装配;如果指定type属性,则按Bean类型进行装配;如果都不指定,则先按Bean的实例名称装配,如果不能匹配,再按照Bean类型进行装配;如果都无法匹配,则抛出 NoSuchBeanDefinitionException异常。

  • @Qualifier:与@Autowired注解配合使用,会将默认的按Bean类型装配修改为Bean的实例名称装配,Bean的实例名称由 @Qualifier注解的参数指定

此时,在配置文件中,Spring注解提供了另外一种高效的注解配置方式。
含义是:告知Spring在创建容器时要扫描的包(通知Spring扫描指定包下的所有Bean)

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

三、自动装配
自动装配:将一个Bean自动地注入到其他Bean的Property中。

Spring的<bean>元素中包含一个 autowire 属性,我们可以通过设置 autowire 的属性值来自动装配Bean。

autowire属性的5个值:

  • default(默认):由的default-autowire属性值来确定。
  • byName:根据属性的名称自动装配。容器将根据名称查找与属性完全一致的Bean,并将其属性自动装配
  • byType:根据属性的数据类型自动装配。
  • constructor:根据构造函数参数的数据类型,进行byType模式的自动装配
  • no:在默认情况下,不使用自动装配,Bean依赖必须通过ref元素定义

写作时间比较仓促且水平有限,可能导致文中很多地方写的比较简略,没有写太多的注释,部分代码请读者根据自己的电脑设置更改配置,也可能还存在大量的错误,欢迎广大猿友不吝指正!

谢谢浏览!

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值