新建Maven工程
修改pom文件
1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http://maven.apache.org/POM/4.0.0" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 5 <modelVersion>4.0.0</modelVersion> 6 <groupId>com.powernode</groupId> 7 <artifactId>spring6-002-dependency-injection</artifactId> 8 <version>1.0-SNAPSHOT</version> 9 <packaging>jar</packaging> 10 11 <!-- 依赖--> 12 <dependencies> 13 <dependency> 14 <groupId>org.springframework</groupId> 15 <artifactId>spring-context</artifactId> 16 <version>5.3.23</version> 17 </dependency> 18 19 <dependency> 20 <groupId>junit</groupId> 21 <artifactId>junit</artifactId> 22 <version>4.13.2</version> 23 <scope>test</scope> 24 </dependency> 25 <!--log4j2的依赖--> 26 <dependency> 27 <groupId>org.apache.logging.log4j</groupId> 28 <artifactId>log4j-core</artifactId> 29 <version>2.19.0</version> 30 </dependency> 31 <dependency> 32 <groupId>org.apache.logging.log4j</groupId> 33 <artifactId>log4j-slf4j2-impl</artifactId> 34 <version>2.19.0</version> 35 </dependency> 36 37 </dependencies> 38 <properties> 39 <maven.compiler.source>17</maven.compiler.source> 40 <maven.compiler.target>17</maven.compiler.target> 41 </properties> 42 43 44 </project>
UserDao.java
package com.lps.dao; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * ClassName: UserDao * Description: * Date: 2022/11/21 16:45 * <author> <time> <version> <desc> * 刘品水 2022/11/21 16:45 @Version 1.0 描述 */ public class UserDao { public static final Logger LOGGER=LoggerFactory.getLogger(UserDao.class); public void insert(){ // System.out.println("数据库正在保存用户信息。。。。"); LOGGER.info("数据库正在保存用户信息。。。。"); } }
VipDao.java
package com.lps.dao; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * ClassName: vipDao * Description: * Date: 2022/11/21 17:16 * <author> <time> <version> <desc> * 刘品水 2022/11/21 17:16 @Version 1.0 描述 */ public class VipDao { public static final Logger LOGGER= LoggerFactory.getLogger(UserDao.class); public void insert(){ // System.out.println("数据库正在保存用户信息。。。。"); LOGGER.info("高级会员正在保存用户信息。。。。"); } }
CostomerSercice.java
1 package com.lps.service; 2 3 import com.lps.dao.UserDao; 4 import com.lps.dao.VipDao; 5 6 /** 7 * ClassName: CostomerSercice 8 * Description: 9 * Date: 2022/11/21 17:35 10 * <author> <time> <version> <desc> 11 * 刘品水 2022/11/21 17:35 @Version 1.0 描述 12 */ 13 public class CostomerSercice { 14 private UserDao userDao; 15 private VipDao vipDao; 16 17 public CostomerSercice(UserDao userDao, VipDao vipDao) { 18 this.userDao = userDao; 19 this.vipDao = vipDao; 20 } 21 22 public void save(){ 23 userDao.insert(); 24 vipDao.insert(); 25 } 26 }
UserService.java
package com.lps.service; import com.lps.dao.UserDao; import com.lps.dao.VipDao; /** * ClassName: UserService * Description: * Date: 2022/11/21 16:48 * <author> <time> <version> <desc> * 刘品水 2022/11/21 16:48 @Version 1.0 描述 */ public class UserService { private UserDao userDao; private VipDao vipDao; public void setVIP(VipDao vipDao){ this.vipDao=vipDao; } //为了显示差别 bane属性为:set方法的方法名去掉set 然后剩下单词的首字母变小写 为了展示出来set方法名我选择为setLpsHHH public void setLpsHHH(UserDao ud) { this.userDao = ud; } //正常用ait+insert直接生成的就很好了 符合规范了 /* public void setUserDao(UserDao userDao) { this.userDao = userDao; }*/ public void saveUser(){ userDao.insert(); vipDao.insert(); }; }
bean.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"> <bean id="userDao" class="com.lps.dao.UserDao"></bean> <bean id="vipDao" class="com.lps.dao.VipDao"></bean> <bean id="costomerSerciceBean1" class="com.lps.service.CostomerSercice"> <constructor-arg index="0" ref="userDao"></constructor-arg> <constructor-arg index="1" ref="vipDao"></constructor-arg> </bean> <bean id="costomerSerciceBean2" class="com.lps.service.CostomerSercice"> <constructor-arg name="userDao" ref="userDao"></constructor-arg> <constructor-arg name="vipDao" ref="vipDao"></constructor-arg> </bean> <bean id="costomerSerciceBean3" class="com.lps.service.CostomerSercice"> <constructor-arg ref="userDao"></constructor-arg> <constructor-arg ref="vipDao"></constructor-arg> </bean> </beans>
log4j2.xml
<?xml version="1.0" encoding="UTF-8"?> <configuration> <loggers> <!-- level指定日志级别,从低到高的优先级: ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF --> <root level="DEBUG"> <appender-ref ref="spring6log"/> </root> </loggers> <appenders> <!--输出日志信息到控制台--> <console name="spring6log" target="SYSTEM_OUT"> <!--控制日志输出的格式--> <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss SSS} [%t] %-3level %logger{1024} - %msg%n"/> </console> </appenders> </configuration>
spring.xml
实现原理:
通过property标签获取到属性名:userDao
通过属性名推断出set方法名:setUserDao
通过反射机制调用setUserDao()方法给属性赋值
property标签的name是属性名。
property标签的ref是要注入的bean对象的id。(通过ref属性来完成bean的装配,这是bean最简单的一种装配方式。装配指的是:创建系统组件之间关联的动作)
<?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="userDaoBean" class="com.lps.dao.UserDao"></bean> <bean id="userServiceBean" class="com.lps.service.UserService"> <!-- 当需要spring调用对应的set方法 需要配置property属性--> <!-- bane属性为:set方法的方法名去掉set 然后剩下单词的首字母变小写 为了展示出来set方法名我选择为setLpsHHH--> <!-- ref翻译为引用 reference 后面指定要注入的bean的id--> <property name="lpsHHH" ref="userDaoBean"></property> <!-- <property name="userDao" ref="userDaoBean"></property> 建议别为难自己 直接用生成的更好 这里只是为了巩固记忆 --> <property name="VIP" ref="vipDaoBean"></property> </bean> <bean name="vipDaoBean" class="com.lps.dao.VipDao"></bean> </beans>
通过测试看到程序仍然可以正常执行,说明property标签的name是:setUserDao()方法名演变得到的。演变的规律是:
- setUsername() 演变为 username
- setPassword() 演变为 password
- setUserDao() 演变为 userDao
- setHaHaHa() 演变为 haHaHa
另外,对于property标签来说,ref属性也可以采用标签的方式,但使用ref属性是多数的:
总结:set注入的核心实现原理:通过反射机制调用set方法来给属性赋值,让两个对象之间产生关系。
测试类
package com.lps; import com.lps.dao.VipDao; import com.lps.service.CostomerSercice; import com.lps.service.UserService; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * ClassName: test * Description: * Date: 2022/11/21 16:56 * <author> <time> <version> <desc> * 刘品水 2022/11/21 16:56 @Version 1.0 描述 */ public class test { @Test public void testConstructor(){ ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean.xml"); CostomerSercice contextBean = context.getBean("costomerSerciceBean1", CostomerSercice.class); contextBean.save(); System.out.println("========="); CostomerSercice contextBean1 = context.getBean("costomerSerciceBean2", CostomerSercice.class); contextBean1.save(); System.out.println("--------"); CostomerSercice contextBean2 = context.getBean("costomerSerciceBean3", CostomerSercice.class); contextBean2.save();
} @Test public void testIoC01(){ ApplicationContext context = new ClassPathXmlApplicationContext("Spring.xml"); UserService userServiceBean = context.getBean("userServiceBean", UserService.class); userServiceBean.saveUser(); // VipDao vipDaoBean = context.getBean("vipDaoBean", VipDao.class); // vipDaoBean.insert(); } }
通过测试 上述testConstructor()得知,通过构造方法注入的时候:
- 可以通过下标
- 可以通过参数名
- 也可以不指定下标和参数名,可以类型自动推断。