赞
踩
Dependency Injection,依赖注入。
Spring 实现的 IoC 容器中,基本类型和对象都可以注入,按配置细节区分:
pom
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>ssm</artifactId> <groupId>com.fengx</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <!--依赖注入--> <artifactId>spring_02</artifactId> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> <spring-version>5.2.2.RELEASE</spring-version> </properties> <!--spring-context--> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring-version}</version> </dependency> </dependencies> <build> </build> </project>
使用 setter 方法演示以上数据类型的注入
bean 的类
package com.fengx.spring_02.datatype; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Set; /** * @author: Fengx * @date: 2021-10-19 * @description: bean 类 **/ public class User { /** * 基本数据类型 */ private double id; /** * 字符串类 */ private String name; /** * 实体类 */ private User wife; /** * 实体数组 */ private User[] friends; /** * List列表 */ private List<User> schoolmates; /** * Set集合 */ private Set<String> favorites; /** * Map集合 */ private Map<String, String> emails; public void setId(double id) { this.id = id; } public void setName(String name) { this.name = name; } public void setWife(User wife) { this.wife = wife; } public void setFriends(User[] friends) { this.friends = friends; } public void setSchoolmates(List<User> schoolmates) { this.schoolmates = schoolmates; } public void setFavorites(Set<String> favorites) { this.favorites = favorites; } public void setEmails(Map<String, String> emails) { this.emails = emails; } /** * 重写 Object 类 toString() * @return */ @Override public String toString() { return "User [id=" + id + ", name=" + name + ", wife=" + wife + ", friends=" + Arrays.toString(friends) + ", schoolmates=" + schoolmates + ", favorites=" + favorites + ", emails=" + emails + "]"; } }
Spring 配置文件
<?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="wife" class="com.fengx.spring_02.datatype.User"> <!--基本数据类型--> <property name="id" value="2"/> <!--字符串--> <property name="name" value="wife"/> </bean> <bean id="fengx_1" class="com.fengx.spring_02.datatype.User"> <!--基本数据类型--> <property name="id" value="1"/> <!--字符串--> <property name="name" value="Fengx"/> <!--对象,ref id 引用 bean 类--> <property name="wife" ref="wife"/> <!--数组--> <property name="friends"> <list> <ref bean="wife"/> </list> </property> <!--list,ref id 引用 bean 类--> <property name="schoolmates"> <list> <ref bean="wife"/> </list> </property> <!--set--> <property name="favorites"> <set> <value>写代码</value> <value>睡觉</value> </set> </property> <!--map--> <property name="emails"> <map> <entry key="公司" value="123@123.com"/> <entry key="个人" value="123@abc.com"/> </map> </property> </bean> <!-- <bean id="specialUser" class="com.fengx.spring_02.datatype.SpecialUser" autowire="byType">--> <!-- </bean>--> </beans>
测试代码
package com.fengx.spring_02.datatype; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.core.env.Environment; /** * @author: Fengx * @date: 2021-10-19 * @description: 依赖注入,可注入的数据类型 * 基本类型 double、String、bean、数组、List、Set、Map 的注入 **/ public class Test { @SuppressWarnings("resource") public static void main(String[] args) { BeanFactory factory = new ClassPathXmlApplicationContext("spring-config-01.xml"); User fengx = (User)factory.getBean("fengx_1"); System.out.println(fengx); // SpecialUser specialUser = (SpecialUser)factory.getBean("specialUser"); // // Spring 自建 bean,并未在 spring-config-01.xml 配置文件中申明,却可以注入与依赖查找 // // 通过 autowire="byType" 可以注入成功 // System.out.println(specialUser.getEnvironment()); // System.out.println(factory.getBean(Environment.class)); // // // 非 bean,可以注入,但无法通过 getBean 方法依赖查找 // // 通过 autowire="byType" 可以注入成功 // System.out.println(specialUser.getBeanFactory()); // // getBean 方法无法获取到 BeanFactory // System.out.println(factory.getBean(BeanFactory.class)); } }
结果打印
User [id=1.0, name=Fengx, wife=User [id=2.0, name=wife, wife=null, friends=null, schoolmates=null, favorites=null, emails=null], friends=[User [id=2.0, name=wife, wife=null, friends=null, schoolmates=null, favorites=null, emails=null]], schoolmates=[User [id=2.0, name=wife, wife=null, friends=null, schoolmates=null, favorites=null, emails=null]], favorites=[写代码, 睡觉], emails={公司=123@123.com, 个人=123@abc.com}]
上面这个例子演示了基本类型 double、String、bean、数组、List、Set、Map 的注入。
那什么是 Spring 自建的 bean 和 非 bean 呢?这两个概念,看下面这个例子。
新增类 SpecialUser,包含了 BeanFactory 和 Environment 两个类型的属性
package com.fengx.spring_02.datatype; import org.springframework.beans.factory.BeanFactory; import org.springframework.core.env.Environment; /** * @author: Fengx * @date: 2021-10-19 * @description: 包含了 BeanFactory 和 Environment 两个类型的属性 **/ public class SpecialUser { private BeanFactory beanFactory; private Environment environment; public BeanFactory getBeanFactory() { return beanFactory; } public void setBeanFactory(BeanFactory beanFactory) { this.beanFactory = beanFactory; } public Environment getEnvironment() { return environment; } public void setEnvironment(Environment environment) { this.environment = environment; } }
xml 新增一个 bean 配置
<bean id="specialUser" class="com.fengx.spring_02.datatype.SpecialUser" autowire="byType">
</bean>
测试类的 main 方法中新增测试代码
package com.fengx.spring_02.datatype; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.core.env.Environment; /** * @author: Fengx * @date: 2021-10-19 * @description: 依赖注入,可注入的数据类型 * 基本类型 double、String、bean、数组、List、Set、Map 的注入 **/ public class Test { @SuppressWarnings("resource") public static void main(String[] args) { BeanFactory factory = new ClassPathXmlApplicationContext("spring-config-01.xml"); // User fengx = (User)factory.getBean("fengx_1"); // System.out.println(fengx); SpecialUser specialUser = (SpecialUser)factory.getBean("specialUser"); // Spring 自建 bean,并未在 spring-config-01.xml 配置文件中申明,却可以注入与依赖查找 // 通过 autowire="byType" 可以注入成功 System.out.println(specialUser.getEnvironment()); System.out.println(factory.getBean(Environment.class)); // // // 非 bean,可以注入,但无法通过 getBean 方法依赖查找 // // 通过 autowire="byType" 可以注入成功 // System.out.println(specialUser.getBeanFactory()); // // getBean 方法无法获取到 BeanFactory // System.out.println(factory.getBean(BeanFactory.class)); } }
打印结果
StandardEnvironment {activeProfiles=[], defaultProfiles=[default], propertySources=[PropertiesPropertySource {name='systemProperties'}, SystemEnvironmentPropertySource {name='systemEnvironment'}]}
StandardEnvironment {activeProfiles=[], defaultProfiles=[default], propertySources=[PropertiesPropertySource {name='systemProperties'}, SystemEnvironmentPropertySource {name='systemEnvironment'}]}
非 bean
package com.fengx.spring_02.datatype; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.core.env.Environment; /** * @author: Fengx * @date: 2021-10-19 * @description: 依赖注入,可注入的数据类型 * 基本类型 double、String、bean、数组、List、Set、Map 的注入 **/ public class Test { @SuppressWarnings("resource") public static void main(String[] args) { BeanFactory factory = new ClassPathXmlApplicationContext("spring-config-01.xml"); // User fengx = (User)factory.getBean("fengx_1"); // System.out.println(fengx); SpecialUser specialUser = (SpecialUser)factory.getBean("specialUser"); // Spring 自建 bean,并未在 spring-config-01.xml 配置文件中申明,却可以注入与依赖查找 // 通过 autowire="byType" 可以注入成功 // System.out.println(specialUser.getEnvironment()); // System.out.println(factory.getBean(Environment.class)); // 非 bean,可以注入,但无法通过 getBean 方法依赖查找 // 通过 autowire="byType" 可以注入成功x System.out.println(specialUser.getBeanFactory()); // getBean 方法无法获取到 BeanFactory System.out.println(factory.getBean(BeanFactory.class)); } }
org.springframework.beans.factory.support.DefaultListableBeanFactory@15975490: defining beans [wife,fengx_1,specialUser]; root of factory hierarchy
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.beans.factory.BeanFactory' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:351)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1126)
at com.fengx.spring_02.datatype.Test.main(Test.java:31)
从打印结果可以看出
依赖注入的实现方式
首先,bean 的配置文件可以通过 xml 和 properties 两种方式。其中 xml 是主流,properties 基本不用,具体实现方式:
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"> <bean id="fengx_2" class="com.fengx.spring_02.impltype.User"> <constructor-arg value="1"/> <property name="name" value="Fengx"/> </bean> <bean id="favorites" class="java.lang.String"> <constructor-arg value="写代码、睡觉"/> </bean> <!-- 开启注解能力 --> <context:component-scan base-package="com.fengx.spring_02"/> </beans>
bean 的类代码
package com.fengx.spring_02.impltype; import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; /** * @author: Fengx * @date: 2021-10-19 * @description: bean 类 **/ public class User implements ApplicationContextAware { /** * 构造方法注入 */ private final Integer id; public User(Integer id) { this.id = id; } /** * set 方法注入 */ private String name; public void setName(String name) { this.name = name; } /** * 实现接口 ApplicationContextAware 及其回调方法注入 applicationContextAware */ private ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } /** * 使用注解,xml需要开启注解能力 * 使用 @Autowired 给属性字段注入 */ @Autowired private String favorites; @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", applicationContext=" + applicationContext + ", friend=" + favorites + '}'; } }
测试代码,包含 bean 通过 api 注册与注入
package com.fengx.spring_02.impltype; import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.PropertyValue; import org.springframework.beans.factory.config.ConstructorArgumentValues; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @author: Fengx * @date: 2021-10-19 * @description: 依赖注入的实现方式 **/ public class Test { @SuppressWarnings("resource") public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-config-02.xml"); User fengx = (User)context.getBean("fengx_2"); System.out.println(fengx); // api 构造、注入、组装、注册 bean DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory)context.getBeanFactory(); AbstractBeanDefinition userBeanDefinition = new RootBeanDefinition(User.class); // 构造方法注入 beanFactory.registerBeanDefinition("ApiUser", userBeanDefinition); ConstructorArgumentValues argValues = new ConstructorArgumentValues(); argValues.addIndexedArgumentValue(0, 1); // set 方法注入 userBeanDefinition.setConstructorArgumentValues(argValues); MutablePropertyValues propertyValues = new MutablePropertyValues(); propertyValues.addPropertyValue(new PropertyValue("name", "ApiUser")); userBeanDefinition.setPropertyValues(propertyValues); System.out.println(beanFactory.getBean("ApiUser")); } }
结果打印
{id=1, name='Fengx', applicationContext=org.springframework.context.support.ClassPathXmlApplicationContext@68de145, started on Tue Oct 19 17:41:03 CST 2021, friend=写代码、睡觉}
User{id=1, name='ApiUser', applicationContext=org.springframework.context.support.ClassPathXmlApplicationContext@68de145, started on Tue Oct 19 17:41:03 CST 2021, friend=写代码、睡觉}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。