目录

依赖注入方式&自动装配

# 依赖注入方式

![[Pasted image 20220611193259.png]]

# setter注入

其实在先前的说明中,不难发现,所谓的依赖也能用于间接实现有参构造,我们可以通过applicationContext.xml中的property标签实现。 继续使用上节中的applicationContext.xml数据作为例子

public class UserServiceImpl implements UserService{  
    UserDao ud;  
    public int age;  
    public String name;  
  
    public void setAge(int age) {  
        this.age = age;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
  
    public void setUd(UserDao ud) {  
        this.ud = ud;  
    }  
  
    @Override  
    public void save() {  
        System.out.println(this.name+this.age);  
    }  
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<bean id="userServiceImpl" class="com.project.service.impl.UserServiceImpl">  
    <property name="ud" ref="userDaoImpl"/>  
    <property name="age" value="10"/>  
    <property name="name" value="LamKaKuan"/>  
</bean>
1
2
3
4
5

我们可以为UserServiceImpl类配置两个简单类型的变量,然后通过property标签填入值,你能看到引用类型用ref,简单类型用value

# 构造器注入

说白了就是有参构造器而已,但不能像以往一样直接一个有参构造器就完事儿了,需要在配置文件中说明才行。

public class UserServiceImpl implements UserService{  
    UserDao ud;  
  
    public UserServiceImpl(UserDao ud){  
        this.ud=ud;  
    }  
  
    @Override  
    public void save() {  
        System.out.println("hello");  
    }  
}
1
2
3
4
5
6
7
8
9
10
11
12
<bean id="userServiceImpl" class="com.project.service.impl.UserServiceImpl">  
    <constructor-arg name="ud" ref="userDaoImpl"/>  
</bean>
1
2
3

不难发现,其实和setter的区别就是多了个有参构造器以及内嵌了新的constructor-arg标签,name属性填写的是有参构造器中参数的名称,ref则是引用类型

这种方式很明显违背了Spring的初衷(解耦合),当你更改参数名时也必须更改配置文件

于是作者又更新了新属性

<bean id="userServiceImpl" class="com.project.service.impl.UserServiceImpl">  
    <constructor-arg index="0" ref="userDaoImpl"/>  
    <constructor-arg index="1" value="10"/>  
</bean>
1
2
3
4

constructor-arg增加一个index作为识别顺序,从而解决耦合,但老实说这没卵用,我换了参数顺序你不就寄了吗

# 选择

![[Pasted image 20220611195459.png]]

# 依赖自动装配

  • IoC容器根据Bean所依赖的资源在容器中自动寻找并注入到Bean中的过程

使用自动装配时,总共两步

  1. 需要被自动装配的变量必须已写有setter方法
  2. bean标签中写有autowire=bytype

# 选项

autowire有以下几个值可选:

  1. byType - 根据类型去判断(同时多个候选则无法使用)
  2. byName - 根据变量名判断
# byType
<bean id="userDaoImpl" class="com.project.dao.impl.UserDaoImpl"/>  
<bean id="userDaoImpl2" class="com.project.dao.impl.UserDaoImpl"/>  
<bean id="userServiceImpl" class="com.project.service.impl.UserServiceImpl" autowire="byType"/>
1
2
3
public class UserServiceImpl implements UserService{  
    UserDao userDao;  
  
  
    public void setUserDao(UserDao userDao) {  
        this.userDao = userDao;  
    }  
  
    @Override  
    public void save() {  
        System.out.println("hello");  
    }  
}
1
2
3
4
5
6
7
8
9
10
11
12
13

假设此时有两个userDao的实现类,对于UserServiceImpl而言就无法判断该装配哪一个了。

# byName

虽然两个实现类很少见,但也并非不存在,真遇到这种问题该如何解决呢? byName选项就是根据名字进行判断

<bean id="userDao" class="com.project.dao.impl.UserDaoImpl"/>  
<bean id="userDao2" class="com.project.dao.impl.UserDaoImpl"/>  
<bean id="userServiceImpl" class="com.project.service.impl.UserServiceImpl" autowire="byName"/>
1
2
3
public class UserServiceImpl implements UserService{  
    UserDao userDao;  
  
  
    public void setUserDao(UserDao userDao) {  
        this.userDao = userDao;  
    }  
  
    @Override  
    public void save() {  
        System.out.println("hello");  
    }  
}
1
2
3
4
5
6
7
8
9
10
11
12
13

那么此时,就会自动装配id为userDao的。这个名字缘由是根据setUserDao函数去除set并将首字母小写得出的。

# 依赖自动装配特征

![[Pasted image 20220612004323.png]]

# 第三方数据管理

以C3P0为例

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">  
     <property name="driverClass" value="com.mysql.cj.jdbc.Driver"/>  
     <property name="jdbcUrl" value="jdbc:mysql:///user_info"/>  
     <property name="user" value="root"/>  
     <property name="password" value="Lam1134312514"/>  
</bean>
1
2
3
4
5
6

其实创建第三方的类也就是在class填写对应类的位置而已。

# Properties

上面第三方例子中不难发现一个问题,我们又把参数写死了,这导致耦合度很高。 因此我们应该利用Properties将数据抽出来单独放置

首先这是resources/jdbc.properties

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql:///user_info
jdbc.username=root
jdbc.password=root
1
2
3
4
  1. 开辟命名空间
<beans xmlns="http://www.springframework.org/schema/beans"  
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
       xmlns:context="http://www.springframework.org/schema/context"  
  
       xsi:schemaLocation="  
       http://www.springframework.org/schema/beans       http://www.springframework.org/schema/beans/spring-beans.xsd       http://www.springframework.org/schema/context       http://www.springframework.org/schema/context/spring-context.xsd">
1
2
3
4
5
6

这是文件头!!!

  1. 使用context空间加载properties文件 在<beans>标签下添加<context:property-placeholder location="jdbc.properties"/>

  2. 使用properties中的变量

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">  
     <property name="driverClass" value="${jdbc.driver}"/>  
     <property name="jdbcUrl" value="${jdbc.url}"/>  
     <property name="user" value="${jdbc.username}"/>  
     <property name="password" value="${jdbc.password}"/>  
</bean>
1
2
3
4
5
6
# 注意

在定义properties文件时你可能注意到了一个问题,为什么我们定义的是jdbc.username而不直接是username呢? 建议在使用此类方法时都加上前缀,因为谁也不知道系统变量中是否恰好有个变量与你重名,系统变量的优先级远高于你的properties变量优先级!

当然,如果你头铁打死不加前缀,那你也能在<context>标签内添加属性system-properties-mode="Never",这个属性告知系统忽视原有的系统变量

# 小技巧

倘若你需要加载多个properties配置文件,有两种方式

  1. 加载所有properties: <context:property-placeholder location="*.properties"/>
  2. 加载特定properties: <context:property-placeholder location="jdbc1.properties,jdbc2.properties"/>

但以上两种方式只能读自己项目的properties文件,如果你想读取第三方jar中的properties,你需要使用<context:property-placeholder location="classpath*:*.properties"/>

![[Pasted image 20220612142220.png]]

最近更新
01
基本知识
07-18
02
卷积神经网络识别图像
07-18
03
损失函数
07-18
更多文章>