目录
注:如果User的bean id与Teacher方法中属性名不一致时,使用name注入出现错误
spring自动装配
Spring 框架提供了一种机制,称为自动装配(Autowired),它允许 Spring 容器自动将依赖注入到 Bean 中,而无需显式地使用 XML 配置文件或构造函数注入。自动装配简化了依赖注入的过程,使得代码更加简洁和易于维护。
1 自动装配的基本概念
自动装配是指 Spring 容器自动为一个 Bean 的属性找到合适的依赖对象,并将其注入。Spring 支持多种自动装配策略,包括:
- no: 默认情况下,Spring 不会自动装配任何 Bean。
- byName: Spring 尝试根据属性名自动装配 Bean。
- byType: Spring 尝试根据类型自动装配 Bean。
- constructor: 类似于 byType,但适用于构造函数参数。
- autodetect: 如果存在带有一个参数的构造函数,则使用 constructor;否则使用 byType。
2 基础环境准备
1.新建module
- 打开现有的Maven项目。
- 添加新模块:
- 在IntelliJ IDEA中,右键点击项目的根目录 ->
New > Module...
-> 选择Maven Module
。 - 在Eclipse中,右键点击项目的
src/main/java
目录 ->New > Other...
-> 选择Maven
类别下的Module
。
- 在IntelliJ IDEA中,右键点击项目的根目录 ->
- 填写模块信息:
- 组织ID (
groupId
):与主项目相同。 - 艺术品ID (
artifactId
):模块的名称。 - 版本 (
version
):与主项目相同。 - 包装 (
packaging
):根据模块的功能选择war
、jar
或pom
。
- 组织ID (
- 完成创建:点击完成按钮,IDE将创建新的模块。
2.导入相关的依赖
在项目的pom.xml文件夹中导入一下依赖
<dependencies>
<!--导入spring-context依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.1.12</version></dependency>
<!--导入测试依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--导入日志框架--><dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.23.1</version>
</dependency><dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j2-impl</artifactId>
<version>2.23.1</version>
</dependency>
</dependencies>
注:导入依赖后需要刷新Maven,否则依赖不会导入
如果没有出现上面这个图标,你则需要进行如下步骤
idea===>最右边的栏===》Maven===>点击打开===》新弹出来的界面中===》点击刷新按钮==》就会出现Maven刷新图标====》点击刷新就能刷新了
3.新建SpringConfig配置文件
配置文件中的内容如下
<?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>
4.创建User类
下面是一个user类,name,age,有参构造,无参数构造,get,set方法
package org.xiji; public class User { private String name; private int age; public User(String name, int age) { this.name = name; this.age = age; }public User() { }public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
5.创建Teacher类
package org.xiji;
public class Teacher {
private User user;
public Teacher(User user) {
this.user = user;
}
public Teacher() {
}
/**
*
* 点名
*/
public void call() {
System.out.println("老师点名"+user.getName()+"同学");
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
3 在 XML 配置中启用自动装配
1.通过类型装配
在SpringConfig.xml中编写配置文件
<!--通过类型--> <bean id="userByType" class="org.xiji.User" autowire="byType"> <property name="age" value="18"></property> <property name="name" value="xiji"></property> </bean> <bean id="teacher" class="org.xiji.Teacher" autowire="byType"> </bean>
测试
注:可以看到,我们并没有配置和获取User相关的信息,但是调用teacher.call()点名方法时,却输出了我们在SpringConfig.xml文件中配置的user,但是我们也要注意,如果这个类有多个实例化对象时,会包错,错误原因是多个实例化对象,但不知道注入哪一个。
2.通过名称装配
在SpringConfig.xml中编写配置文件
<!--通过名字--> <bean id="teacher" class="org.xiji.Teacher" autowire="byName"> </bean> <bean id="user" class="org.xiji.User" autowire="byName"> <property name="age" value="18"></property> <property name="name" value="张三"></property> </bean>
测试结果
可以看到依旧可以成功
注:如果User的bean id与Teacher方法中属性名不一致时,使用name注入出现错误
修改配置文件
<?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="teacher" class="org.xiji.Teacher" autowire="byName">
</bean>
<bean id="userByName" class="org.xiji.User" autowire="byName">
<property name="age" value="18"></property>
<property name="name" value="张三"></property>
</bean>
</beans>
错误收集
java.lang.NullPointerException: Cannot invoke "org.xiji.User.getName()" because "this.user" is null
at org.xiji.Teacher.call(Teacher.java:19)
at ByTypeTest.test(ByTypeTest.java:13)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
解决办法:
注入时,使用正确的名字,即可解决
4. 使用@Autowired注解中使用自动装配
1.配置componentScan包扫描
下面方法任选其中一种
1)在SpringConfig.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" 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 "><!--配置包扫描--><context:component-scan base-package="org.xiji"></context:component-scan></beans>
注:把红色的替换为你自己的包路径,经过包扫描可以使用注解
2)配置类中配置
注:需要新建一个配置类,并且在类上加入@Configuration 和@ComponentScan("包名")
package org.xiji.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("org.xiji")
public class MyConfig {
}
2.@Autowired的使用
这里用javaweb中的视图控制层Controller和业务逻辑层Service层调用为例
1)基础准备
controller
package org.xiji.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.xiji.service.WebService; @Controller public class WebController { @Autowired WebService webService; /** * 调用service */ public void call() { webService.call(); } }
注:
@Autowired 自动装配注解
@Controller 这个是标注controller注解
@Resource 这个也是自动装配的注解
service
service接口
package org.xiji.service; public interface WebService { public void call(); }
service接口实现类
package org.xiji.service.impl; import org.springframework.stereotype.Service; import org.xiji.service.WebService; @Service public class WebServiceImpl implements WebService { public void call() { System.out.println("你好啊,我的Spring"); } }
注:
@Service是service层的注解
2)测试
1.通过xml文件扫描配置文件测试
/**
* 通过xml配置文件创建对象
*/
@Test
public void test(){
System.out.println("通过xml配置文件创建对象");
ApplicationContext context = new ClassPathXmlApplicationContext("SpringConfig.xml");
WebController webController = context.getBean("webController", WebController.class);
webController.call();
}
2.通过config配置类测试
/**
* 通过配置类创建对象
*/
@Test
public void test2(){
System.out.println("通过配置类创建对象");
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
WebController webController = context.getBean("webController", WebController.class);
webController.call();
}