Spring中的依赖注入

依赖注入(DI):

依赖注入(DI)是指IC容器在运行期间动态地将某种依赖资源注入到对象中。

例如,将对象B注人(赋值)给对象A的成员变量。

依赖注入的基本思想是,明确地定义组件接口,独立开发各个组件,然后根据组件的依赖关系组装运行。

依赖注入的类型:

构造方法注入

package com.itheima;

public class User1 {
    private int id;
    private String name;
    private String password;
    public User1(int id, String name, String password) {
        this.id = id;
        this.name = name;
        this.password = password;
    }

    @Override
    public String toString() {
        return "User1{" +
                "id=" + id +
                ", name='" + name + '\\'' +
                ", password='" + password + '\\'' +
                '}';
    }
}

配置文件
<?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="user1" class="com.itheima.User1">
            <constructor-arg name="id" value="1"></constructor-arg>
            <constructor-arg name="name" value="张三"></constructor-arg>
            <constructor-arg name="password" value="123"></constructor-arg>
        </bean>
</beans>

测试类
package com.itheima;

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

public class TestUser1 {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext-User.xml");
        User1 user1 = applicationContext.getBean("user1", User1.class);
        System.out.println(user1);
    }

}

属性 setter 方法注入

package com.itheima;

public class User2 {
    private int id;
    private String name;
    private String password;

    public void setId(int id) {
        this.id = id;
    }

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

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User1{" +
                "id=" + id +
                ", name='" + name + '\\'' +
                ", password='" + password + '\\'' +
                '}';
    }
}

配置文件
<?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="user2" class="com.itheima.User2">
        <property name="id" value="2"/>
        <property name="name" value="李四"/>
        <property name="password" value="456"/>
    </bean>
</beans>

测试方法
package com.itheima;

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

public class TestUser2 {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext-User2.xml");
        User2 user2 = applicationContext.getBean("user2", User2.class);

        System.out.println(user2);
    }
}

下面是一个例子实现依赖注入:

使用依赖注入实现登陆验证

编写Service层

创建UserService接口

package com.itheima.service;

//业务逻辑层接口
public interface UserService {
    public boolean login(String name, String password);
}

创建UserService接口的实现类UserServiceImpl

package com.itheima.service.impl;

//import com.itheima.service.UserService;
import com.itheima.service.UserService;
import org.springframework.jdbc.core.JdbcTemplate;

public class UserServiceImpl implements UserService {

    private JdbcTemplate jdbcTemplate;

    @Override
    public boolean login(String username, String password) {
        String sql = "SELECT count(*) FROM users WHERE username = ? AND password = ?";
        Integer count = jdbcTemplate.queryForObject(sql, new Object[]{username, password}, Integer.class);
        return count != null && count > 0;
    }

    //此Setter方法用于注入JdbcTemplate实例。
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
}

  • jdbcTemplate.queryForObject: 使用**JdbcTemplatequeryForObject**方法执行SQL查询。
    • sql: 第一个参数是要执行的SQL查询字符串。
    • new Object[]{username, password}: 第二个参数是一个对象数组,包含要绑定到SQL查询中的参数值(用户名和密码)。
    • Integer.class: 第三个参数是返回结果的类型,表示期望结果是一个整数。

这种方法利用**JdbcTemplate**简化了数据库操作,避免了手动管理数据库连接和结果集的繁琐步骤,同时通过占位符防止SQL注入攻击

下面解释一下sql注入攻击:

public boolean findAdmin(Admin admin)
    {
    String sql = "select count(*) from admin where username='" + admin.getUsername() + "'and password='" + admin.getPassword() + "'"  //SQL查询语句
    try {
        Resultset res = this.conn.creatStatement().executQuery(sql);
        //执行sql语句
        if(res.next())
        {
            int i = res.getInt(1);//获取第一列的值
            if (i>0)
            {return true;} //如果结果大于0,则返回true
        }
        } catch (Exception e) {
        e.printStackTree();//打印异常信息
        }
        return false;
    }

正常情况下,当一个用户 username='test'且password='test'时,执行了sql语句 select count() from admin where username = 'test' and password = 'test'

但是当输入username="'or 1=1--"时,在java程序中String类型变量sql 为 " select count() from admin where username = ' 'or 1=1-- ' and password = ' ' "这句sql语句在执行时,"--" 将"and"及之后的语句都注释掉了,相当于执行了select count(*) from admin where username = ' 'or 1=1 而1=1是永远为true的,所以该语句的执行结果实际上是admin表的行数,而不是符合输入的username和password的行数,从而顺利通过验证。

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

    <!-- 配置JDBC数据源 -->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost/spring?useUnicode=true
                                    &amp;characterEncoding=utf-8
                                    &amp;serverTimezone=Asia/Shanghai
                                    &amp;useSSL=false"/>
        <property name="username" value="bge"/>
        <property name="password" value="123456"/>
    </bean>
    <!-- 配置JDBC模板 -->
    <bean id="JdbcTemplate"
          class="org.springframework.jdbc.core.JdbcTemplate">
        <!-- 默认必须使用数据源 -->
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- userService bean配置了UserServiceImpl类,
    并通过<property>标签指定要注入的jdbcTemplate bean -->
    <bean id="userService" class="com.itheima.service.impl.UserServiceImpl">
        <property name="jdbcTemplate" ref="JdbcTemplate"/>
    </bean>

</beans>

编写测试类

package com.itheima;

import com.itheima.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.Scanner;

public class TestSpring {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = (UserService) applicationContext.getBean("userService");

        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入要登录的用户账号");
        String username = scanner.nextLine();
        System.out.println("请输入密码");
        String password = scanner.nextLine();

        boolean flag = userService.login(username, password);
        if (flag)
            System.out.println("登录成功");
        else
            System.out.println("登录失败");
    }
}

依赖注入的工作原理

  1. Spring容器启动: Spring容器根据配置文件**applicationContext.xml**创建并初始化所有的bean。
  2. 创建dataSource bean: Spring容器首先创建并初始化**dataSource** bean。
  3. 创建jdbcTemplate bean: Spring容器接着创建并初始化**jdbcTemplate** bean,并将**dataSource** bean注入到**jdbcTemplate** bean中。
  4. 创建userService bean: Spring容器创建并初始化**userService** bean,即**UserServiceImpl**实例。
  5. Setter注入
    • Spring容器识别到**<property name="jdbcTemplate" ref="jdbcTemplate"/>**。
    • 容器调用**UserServiceImplsetJdbcTemplate方法,并传递jdbcTemplate** bean实例。

Spring容器在创建**UserServiceImpl实例时,会自动调用setJdbcTemplate方法,将JdbcTemplate实例注入到UserServiceImpl**中,从而实现依赖注入。

总结

依赖注入(DI)和控制反转(IoC)是从不同角度来描述了同一件事情。依赖注入是从应用程序的角度描述,即应用程序依赖IoC容器创建并注入它所需要的外部资源:而控制反转是从IoC容器的角度描述,即IoC容器控制应用程序,由IoC容器反向地向应用程序注人应用程序所需要的外部资源。这里所说的外部资源可以是外部实例对象,也可以是外部文件对象等。

  • 22
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值