Spring对IOC的实现

控制反转IOC

+ 控制反转是一种思想 + 控制反转是为了降低程序耦合度,提高程序扩展力,达到OCP原则,达到DIP原则 + 控制反转,反转是什么? - 将对象的创建权利交出去,交给第三方容器负责 - 将对象和对象之间关系的维护权交出去,交给第三方容器负责 + 控制反转这种思想如何实现: - DI(Dependency Injection):依赖注入

依赖注入DI

依赖注入 实现了控制反转的思想

Spring通过依赖注入的方式来完成Bean管理

Bean管理:Bean对象的创建,Bean对象中属性的赋值(Bean对象之间关系的维护)

依赖注入:

- 依赖指的是对象和对象之间的关联关系
- 注入指的是一种数据传递行为,通过注入行为来让对象和对象之间产生关系

依赖注入常见的实现方式:

✅第一种:set注入

set注入是居于set方法实现的,底层通过反射机制调用属性对象的set方法然后给属性赋值,让两个对象之间产生关系。这种方式要求属性必须对外提供set方法。

✅第一种:构造方法注入

核心原理:通过调用构造方法来给属性赋值

依赖注入代码实例

set注入
> 注意点: > > 1. 在bean标签中class对标的都是类,所以在MVC架构中填写实现类的实现接口是不可行的 > 2. property的name是set方法的XXX,比如示例中userDao对应的方法就是实现类中的setUserDao方法 > + 通过property标签获取到属性名:userDao > + 通过属性名推断出set方法名:setUserDao > + 通过反射机制调用setUserDao()方法给属性赋值 > - property标签的`** name**`是属性名。 > - property标签的`** ref**`是要注入的bean对象的id。(** 通过ref属性来完成bean的装配,这是bean最简单的一种装配方式**。装配指的是:** 创建系统组件之间关联的动作**) > + 由此可以推断出: > - setUsername() 演变为 username > - setPassword() 演变为 password > - setUserDao() 演变为 userDao > - setUserService() 演变为 userService >
<?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.powernode.Dao.UserDaoImpl"/><bean id="userServiceBean" class="com.powernode.Service.UserServiceImpl"><property name="userDao" ref="userDaoBean"/></bean>
</beans>
package com.powernode.Dao;/*** @Author: -* @Description: TODO* @DateTime: 2024/9/19 15:19*/
public interface UserDao {void add();void update();
}---------------------------------------------------------------------------------package com.powernode.Dao;/*** @Author: * @Description: TODO* @DateTime: 2024/9/19 15:19*/
public class UserDaoImpl implements UserDao{@Overridepublic void add() {System.out.println("Mysql数据库正在新增用户....");}@Overridepublic void update() {System.out.println("Mysql数据库正在修改用户....");}
}
package com.powernode.Service;/*** @Author: * @Description: TODO* @DateTime: 2024/9/19 15:19*/
public interface UserService {void add();void update();
}package com.powernode.Service;import com.powernode.Dao.UserDao;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;---------------------------------------------------------------------------------/*** @Author: * @Description: TODO* @DateTime: 2024/9/19 15:19*/
public class UserServiceImpl implements UserService{private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);public UserDao userDao;public void setUserDao(UserDao userDao){this.userDao = userDao;}@Overridepublic void add() {logger.info("add():userDao:{}", userDao);userDao.add();}@Overridepublic void update() {logger.info("update():userDao:{}", userDao);userDao.update();}
}

测试程序

package com.powernode.Test;import com.powernode.Service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;/*** @Author: * @Description: TODO* @DateTime: 2024/9/23 16:29*/
public class Test {private Logger logger = LoggerFactory.getLogger(Test.class);@org.junit.Testpublic void setTest(){ApplicationContext beans = new ClassPathXmlApplicationContext("beansSetDI.xml");UserService userServiceBean = (UserService) beans.getBean("userServiceBean");userServiceBean.add();/*** userDao:com.powernode.Dao.UserDaoImpl@6e4de19b* Mysql数据库正在新增用户....*/userServiceBean.update();/*** userDao:com.powernode.Dao.UserDaoImpl@6e4de19b* Mysql数据库正在修改用户....*/}
}
构造函数注入
> 构造函数的引用非简单类型和set一样,都是使用`** ref**`引用当前配置文件中已经定义的bean id > > 1. 构造函数的constructor-arg表示定义构造函数的参数,其中存在两种写法 > - index,index表示参数的个数,0表示第一个参数,以此类推 > - name标识参数名称,name所对应的并非参数类型,而是参数命名,比如参数为:"UserDao abcd",那么配置文件中应该这么写:name="abcd" >
<?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.powernode.Dao.UserDaoImpl"/><!--第一种写法,使用index标识参数--><bean id="userServiceBean" class="com.powernode.Service.UserServiceImpl2"><constructor-arg index="0" ref="userDaoBean"/></bean><!--第二种写法,使用name标识参数,name所对应的并非参数类型,而是参数命名--><bean id="userServiceBean2" class="com.powernode.Service.UserServiceImpl2"><constructor-arg name="userDao" ref="userDaoBean"/></bean>
</beans>
package com.powernode.Dao;/*** @Author: * @Description: TODO* @DateTime: 2024/9/19 15:19*/
public interface UserDao {void add();void update();
}---------------------------------------------------------------------------------package com.powernode.Dao;/*** @Author: * @Description: TODO* @DateTime: 2024/9/19 15:19*/
public class UserDaoImpl implements UserDao{@Overridepublic void add() {System.out.println("Mysql数据库正在新增用户....");}@Overridepublic void update() {System.out.println("Mysql数据库正在修改用户....");}
}
package com.powernode.Service;/*** @Author: * @Description: TODO* @DateTime: 2024/9/19 15:19*/
public interface UserService {void add();void update();
}------------------------------------------------------------------------------------package com.powernode.Service;import com.powernode.Dao.UserDao;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;/*** @Author: * @Description: TODO* @DateTime: 2024/9/19 15:19*/
public class UserServiceImpl2 implements UserService{private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl2.class);public UserDao userDao;public UserServiceImpl2(UserDao userDao){this.userDao = userDao;}@Overridepublic void add() {logger.info("add():userDao:{}", userDao);userDao.add();}@Overridepublic void update() {logger.info("update():userDao:{}", userDao);userDao.update();}
}

测试程序

package com.powernode.Test;import com.powernode.Service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;/*** @Author: * @Description: TODO* @DateTime: 2024/9/23 16:29*/
public class Test {private Logger logger = LoggerFactory.getLogger(Test.class);@org.junit.Testpublic void constructorTest(){ApplicationContext beans = new ClassPathXmlApplicationContext("beansConstructor.xml");UserService userServiceBean = (UserService) beans.getBean("userServiceBean2");userServiceBean.add();/**2024-09-23 17:00:10 397 [main] INFO com.powernode.Service.UserServiceImpl2 - add():userDao:com.powernode.Dao.UserDaoImpl@7adf16aaMysql数据库正在新增用户....*/userServiceBean.update();/**2024-09-23 17:00:10 410 [main] INFO com.powernode.Service.UserServiceImpl2 - update():userDao:com.powernode.Dao.UserDaoImpl@7adf16aaMysql数据库正在修改用户....*/}
}

set注入专题

注入外部Bean
注入外部Bean的意思是在配置property标签时,采用ref的形式配置
<?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"><!-- set内外部注入bean  --><bean id="userDaoBean" class="com.powernode.Dao.UserDaoImpl"/><!--外部注入--><bean id="userServiceBean" class="com.powernode.Service.UserServiceImpl"><property name="userDao" ref="userDaoBean"/></bean>
</beans>
@org.junit.Test
public void shapeTest(){ApplicationContext beans = new ClassPathXmlApplicationContext("beansShape.xml");UserService userServiceBean = (UserService) beans.getBean("userServiceBean");UserDao userDaoBean = (UserDao) beans.getBean("userDaoBean");logger.info("userDaoBean:{}", userDaoBean);// userDaoBean:com.powernode.Dao.UserDaoImpl@18518ccfuserServiceBean.add();/**add():userDao:com.powernode.Dao.UserDaoImpl@18518ccfMysql数据库正在新增用户....*/userServiceBean.update();/**update():userDao:com.powernode.Dao.UserDaoImpl@18518ccfMysql数据库正在修改用户....*/
}
注入内部Bean
注入外部Bean的意思是在配置property标签时,现阶段直接创建;

与外部注入Bean的区别:外部注入Bean中ref引用的和userService使用的对象是同一个对象;内部注入因为是新创建的,所以每一个创建出来的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"><!-- set内外部注入bean  --><bean id="userDaoBean" class="com.powernode.Dao.UserDaoImpl"/><!--内部注入--><bean id="userServiceBean" class="com.powernode.Service.UserServiceImpl"><property name="userDao"><bean class="com.powernode.Dao.UserDaoImpl"/></property></bean>
</beans>
@org.junit.Test
public void shapeTest(){ApplicationContext beans = new ClassPathXmlApplicationContext("beansShape.xml");UserService userServiceBean = (UserService) beans.getBean("userServiceBean");UserDao userDaoBean = (UserDao) beans.getBean("userDaoBean");logger.info("userDaoBean:{}", userDaoBean);// userDaoBean:com.powernode.Dao.UserDaoImpl@4c6daf0userServiceBean.add();/**add():userDao:com.powernode.Dao.UserDaoImpl@6d0b5bafMysql数据库正在新增用户....*/userServiceBean.update();/**update():userDao:com.powernode.Dao.UserDaoImpl@6d0b5bafMysql数据库正在修改用户....*/
}
注入简单类型
进行注入的时候,对象的属性是另外一个对象的时候,我们使用`set`+ `ref`注入。如果注入的对象属性是基本数据类型,也是采用set注入的方式给该属性赋值。

注意点:

property标签的name属性为set方法去掉set后的首字母小写

<?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="user" class="com.powernode.entity.User"><property name="age" value="20"/></bean><!--完整写法--><bean id="userBean" class="com.powernode.entity.User"><property name="age"><value>22</value></property></bean>
</beans>
    @org.junit.Testpublic void userTest(){ApplicationContext beans = new ClassPathXmlApplicationContext("simpleType.xml");User user = (User) beans.getBean("user");User user2 = (User) beans.getBean("userBean");System.out.println(user.toString());//  User{age=20}System.out.println(user2);}
简单类型
简单类型包括哪些?
    public static boolean isSimpleValueType(Class<?> type) {return !isVoidType(type) && (isPrimitiveOrWrapper(type) || Enum.class.isAssignableFrom(type) || CharSequence.class.isAssignableFrom(type) || Number.class.isAssignableFrom(type) || Date.class.isAssignableFrom(type) || Temporal.class.isAssignableFrom(type) || ZoneId.class.isAssignableFrom(type) || TimeZone.class.isAssignableFrom(type) || File.class.isAssignableFrom(type) || Path.class.isAssignableFrom(type) || Charset.class.isAssignableFrom(type) || Currency.class.isAssignableFrom(type) || InetAddress.class.isAssignableFrom(type) || URI.class == type || URL.class == type ||UUID.class == type || Locale.class == type || Pattern.class == type || Class.class == type);}// 分析 isPrimitiveOrWrapperpublic static boolean isPrimitiveOrWrapper(Class<?> clazz) {Assert.notNull(clazz, "Class must not be null");return clazz.isPrimitive() || isPrimitiveWrapper(clazz);}/*** Determines if the specified {@code Class} object represents a* primitive type.** <p> There are nine predefined {@code Class} objects to represent* the eight primitive types and void.  These are created by the Java* Virtual Machine, and have the same names as the primitive types that* they represent, namely {@code boolean}, {@code byte},* {@code char}, {@code short}, {@code int},* {@code long}, {@code float}, and {@code double}.** <p> These objects may only be accessed via the following public static* final variables, and are the only {@code Class} objects for which* this method returns {@code true}.** @return true if and only if this class represents a primitive type** @see     java.lang.Boolean#TYPE* @see     java.lang.Character#TYPE* @see     java.lang.Byte#TYPE* @see     java.lang.Short#TYPE* @see     java.lang.Integer#TYPE* @see     java.lang.Long#TYPE* @see     java.lang.Float#TYPE* @see     java.lang.Double#TYPE* @see     java.lang.Void#TYPE* @since 1.1*/@IntrinsicCandidatepublic native boolean isPrimitive();

由源码可知简单类型包括:

基本数据类型、基本类型对应的包装类、String或者其他的****CharSequence子类、Enum子类、Number子类、Date子类、URIURLTemporal子类LocalClass、ZoneId、TimeZone、File、Path、Charset、Currency、InetAddress、UUID、Pattern

简单类型代码示例
> 注意:这里只测常见的,** Currency、InetAddress等**工具类不做测试 >
<?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"><!--&lt;!&ndash;简化写法&ndash;&gt;--><!--<bean id="user" class="com.powernode.entity.User">--><!--    <property name="age" value="20"/>--><!--</bean>--><!--&lt;!&ndash;完整写法&ndash;&gt;--><!--<bean id="userBean" class="com.powernode.entity.User">--><!--    <property name="age">--><!--        <value>22</value>--><!--    </property>--><!--</bean>--><bean id="simpleTypeBean" class="com.powernode.entity.AllSimpleType"><!--基本数据类型--><property name="b" value="2"/><property name="s" value="3"/><property name="i" value="30"/><property name="l" value="20000000"/><property name="f" value="20.1"/><property name="d" value="20.222"/><property name="flag" value="true"/><property name="c" value="s"/><!--基本数据类的包装类--><property name="b1" value="3"/><property name="s1" value="4"/><property name="i1" value="40"/><property name="l1" value="999999999999999"/><property name="f1" value="21.1"/><property name="d1" value="21.222"/><property name="flag1" value="false"/><property name="c1" value="b"/><!--String--><property name="str" value="mySimpleType"/><!--注意:value后面的日期字符串格式必须是Date对象的toString()方法执行的结果--><!--如果想使用其他格式的日期字符串,就需要进行特殊处理--><property name="date" value="Fri Sep 30 15:26:38 CST 2022"/><!--枚举 Enum--><property name="season" value="WINTER"/><!--uri--><property name="uri" value="/save.do"/><!--url  spring6之后,会自动检查url是否有效,如果无效会报错--><property name="url" value="http://www.baidu.com"/><!--localDate--><property name="localDate" value="EPOCH"/><!--localjava.util.Locale 主要在软件的本地化时使用。它本身没有什么功能,更多的是作为一个参数辅助其他方法完成输出的本地化。--><property name="locale" value="CHINESE"/><!--class--><property name="clazz" value="com.powernode.entity.AllSimpleType"/></bean>
</beans>
    @org.junit.Testpublic void simpleType(){ApplicationContext beans = new ClassPathXmlApplicationContext("simpleType.xml");AllSimpleType simpleTypeBean = (AllSimpleType) beans.getBean("simpleTypeBean");System.out.println(simpleTypeBean);/**AllSimpleType{b=2, s=3, i=30, l=20000000, f=20.1, d=20.222, flag=true, c=s, b1=3, s1=4, i1=40, l1=999999999999999, f1=21.1, d1=21.222, flag1=false, c1=b, str='mySimpleType', date=Sat Oct 01 05:26:38 CST 2022, season=WINTER, uri=/save.do, url=http://www.baidu.com, localDate=1970-01-01, locale=chinese, clazz=class com.powernode.entity.AllSimpleType}*/}
  • 如果把Date当做简单类型的话,日期字符串格式不能随便写。格式必须符合Date的toString()方法格式。显然这就比较鸡肋了。如果我们提供一个这样的日期字符串:2010-10-11,在这里是无法赋值给Date类型的属性的。
  • spring6之后,当注入的是URL,那么这个url字符串是会进行有效性检测的。如果是一个存在的url,那就没问题。如果不存在则报错。
级联属性赋值(了解)
```xml <?xml version="1.0" encoding="UTF-8"?>
<property name="name" value="张三"/><!--要点1:以下两行配置的顺序不能颠倒-->
<property name="clazz" ref="clazzBean"/>
<!--要点2:clazz属性必须有getter方法-->
<property name="clazz.name" value="高三一班"/>
```
package com.rui.spring6.beans;public class Clazz {private String name;//无惨构造public Clazz() {}//有参构造public Clazz(String name) {this.name = name;}//setter and getterpublic void setName(String name) {this.name = name;}public String getName() {return name;}@Overridepublic String toString() {return "Clazz{" +"name='" + name + '\'' +'}';}
}

使用级联属性赋值需要注意两点:

1、配置的顺序不能颠倒

2、clazz属性必须提供getter方法

注入数组
注入数组根据数组类型分为两种:简单类型、非简单类型
  • 如果数组中是简单类型,使用value标签
  • 如果数组中是非简单类型,使用ref标签
<?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="goods1" class="com.powernode.entity.Goods"><property name="name" value="香蕉"/></bean><bean id="goods2" class="com.powernode.entity.Goods"><property name="name" value="苹果"/></bean><!--数组类型简单类型--><bean id="personBean" class="com.powernode.entity.Person"><property name="favariteFoods"><array><value>鸡排</value><value>汉堡</value><value>鹅肝</value></array></property></bean><!--数组类型非简单类型--><bean id="orderBean" class="com.powernode.entity.Order"><property name="goods"><array><!--使用ref标签定位 bean属性选择对象--><ref bean="goods1"/><ref bean="goods2"/></array></property></bean>
</beans>
    @org.junit.Testpublic void simpleArrayType(){ApplicationContext beans = new ClassPathXmlApplicationContext("beans-array-type.xml");Person personBean = (Person) beans.getBean("personBean");System.out.println(personBean);//Person{favariteFoods=[鸡排, 汉堡, 鹅肝]}Order orderBean = (Order) beans.getBean("orderBean");System.out.println(orderBean);//Order{goods=[Goods{name='香蕉'}, Goods{name='苹果'}]}}
注入List集合
> List集合:有序可重复。 > > + 注入List集合的时候使用标签 > + List集合中是简单类型使用`value`标签,反之使用`ref`标签 >
<?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="goods1" class="com.powernode.entity.Goods"><property name="name" value="香蕉"/></bean><bean id="goods2" class="com.powernode.entity.Goods"><property name="name" value="苹果"/></bean><bean id="dataStructureBean" class="com.powernode.entity.DataStructure"><!--list  使用list标签 无序列表--><property name="list"><list><value>listOne</value><value>listTwo</value></list></property></bean>
</beans>
注入Set集合
> + 使用标签。 > + set集合中元素是简单类型的使用`value`标签,反之使用`ref`标签 >
<?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="goods1" class="com.powernode.entity.Goods"><property name="name" value="香蕉"/></bean><bean id="goods2" class="com.powernode.entity.Goods"><property name="name" value="苹果"/></bean><bean id="dataStructureBean" class="com.powernode.entity.DataStructure"><!--set 使用set 有序列表--><property name="set"><set><value>setOne</value><value>setThree</value><value>setOneW</value></set></property></bean>
</beans>
注入Map集合
> + 使用 标签。 > + 如果key是简单类型,使用key属性,反之使用`key-ref`属性 > + 如果value是简单类型,使用value属性,反之使用`value-ref`属性 >
<?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="goods1" class="com.powernode.entity.Goods"><property name="name" value="香蕉"/></bean><bean id="goods2" class="com.powernode.entity.Goods"><property name="name" value="苹果"/></bean><bean id="dataStructureBean" class="com.powernode.entity.DataStructure"><!--Map 分为简单类型、非简单类型value--><property name="simpleMap"><map><entry key="1" value="上海普陀区"/><entry key="2" value="上海浦东新区"/><entry key="3" value="上海长宁区"/></map></property><property name="classMap"><map><entry key="1" value-ref="goods1"/><entry key="2" value-ref="goods2"/></map></property></bean>
</beans>
注入Properties
> + java.util.Properties继承java.util.Hashtable,所以Properties也是一个Map集合 > + 使用 标签嵌套 标签完成 >
<?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="goods1" class="com.powernode.entity.Goods"><property name="name" value="香蕉"/></bean><bean id="goods2" class="com.powernode.entity.Goods"><property name="name" value="苹果"/></bean><bean id="dataStructureBean" class="com.powernode.entity.DataStructure"><property name="properties"><props><prop key="driver">com.mysql.cj.jdbc.Driver</prop><prop key="url">jdbc:mysql://localhost:3306/spring</prop><prop key="username">root</prop><prop key="password">root</prop></props></property></bean>
</beans>
注入null和空字符串
> 注入空字符串使用:`****` 或者 `**value=""**`**** > > 注入null使用:`****` 或者 **不为该属性赋值** >
<?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="goods1" class="com.powernode.entity.Goods"><property name="name" value="香蕉"/></bean><bean id="goods2" class="com.powernode.entity.Goods"><property name="name" value="苹果"/></bean><bean id="dataStructureBean" class="com.powernode.entity.DataStructure"><!--空字符串--><!--第一种写法--><!--<property name="emptyString">--><!--    <value/>--><!--</property>--><!--第二种写法--><property name="emptyString" value=""></property><!--null  第一种写法--><!--<property name="nullString">--><!--    <null/>--><!--</property>--><!--第二种写法 不写--></bean>
</beans>
注入的值含有特殊字符
XML中由5个特殊字符,分别是`<`、`>`、`'`、`"`、`&`。以上五个特殊字符在XML中会被特殊对待,会被当做XML语法中的一部分进行解析,如果这些特殊字符直接出现在注入的字符串当中,就会报错。

解决方案

  1. 使用转义字符代替特殊符号
  2. 使用<font style="color:#DF2A3F;"><![CDATA[]]></font>,将含有特殊符号的字符串放到<font style="color:#DF2A3F;"><![CDATA[]]></font>当中。放在CDATA区的数据不会被XML文件解析器解析。但是注意,使用CDATA时,不能使用value属性,要使用value标签。
特殊字符转义字符
>>
<<
'
""
&&
<?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="mathBean" class="com.powernode.entity.MathBean"><!--当使用<![CDATA[]]> 时,只能使用value标签,不能使用value属性--><property name="compare"><value><![CDATA[2<3]]></value></property></bean><!--第二种方式--><bean id="mathBean2" class="com.powernode.entity.MathBean"><property name="compare"><value>2 &lt; 3</value></property></bean>
</beans>
package com.powernode.entity;/*** @Author: * @Description: TODO* @DateTime: 2024/9/23 21:22*/
public class MathBean {private String compare;public String isCompare() {return compare;}public void setCompare(String compare) {this.compare = compare;}@Overridepublic String toString() {return "MathBean{" +"compare=" + compare +'}';}
}
    @org.junit.Testpublic void specialType(){ApplicationContext beans = new ClassPathXmlApplicationContext("beans-special-type.xml");MathBean mathBean = (MathBean) beans.getBean("mathBean");System.out.println(mathBean);//MathBean{compare=2<3}MathBean mathBean2 = (MathBean) beans.getBean("mathBean2");System.out.println(mathBean2);//MathBean{compare=2<3}}

P命名空间注入

1. P命名空间注入是为了简化set注入,本质上还是set注入,所以对应属性的Set方法依旧不可少 2. 使用P命名空间注入法需要添加 `xmlns:p="[http://www.springframework.org/schema/p"](http://www.springframework.org/schema/p")` 头 3. P命名注入法采用 `p:属性名="属性值"`的方法注入
package com.powernode.entity;import java.util.Arrays;public class Table {private String name;private Clazz clazz;// 一个订单中有多个商品private Goods[] goods;public Table() {}public Table(String name, Clazz clazz, Goods[] goods) {this.name = name;this.clazz = clazz;this.goods = goods;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Clazz getClazz() {return clazz;}public void setClazz(Clazz clazz) {this.clazz = clazz;}public Goods[] getGoods() {return goods;}public void setGoods(Goods[] goods) {this.goods = goods;}@Overridepublic String toString() {return "Table{" +"name='" + name + '\'' +", clazz=" + clazz +", goods=" + Arrays.toString(goods) +'}';}
}
<?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:p="http://www.springframework.org/schema/p"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="goods1" class="com.powernode.entity.Goods"><property name="name" value="香蕉"/></bean><bean id="tableBean" class="com.powernode.entity.Table" p:name="chen" p:clazz="com.powernode.entity.Table" p:goods-ref="goods1"></bean></beans>
    @org.junit.Testpublic void PSetType(){ApplicationContext beans = new ClassPathXmlApplicationContext("beans-P-type.xml");Table tableBean = (Table) beans.getBean("tableBean");System.out.println(tableBean);// Table{name='chen', clazz=Clazz{name='com.powernode.entity.Table'}, goods=[Goods{name='香蕉'}]}}

C命名空间注入

1. c命名空间是简化构造方法注入的。 2. 使用c命名空间的两个前提条件: + 第一:需要在xml配置文件头部添加信息: - ` xmlns: c ="http://www.springframework.org/schema/c"` + 第二:需要提供构造方法。

3、使用c:_0 下标方式

        c:name 参数名方式
package com.powernode.entity;/*** @Author: * @Description: TODO* @DateTime: 2024/9/23 21:22*/
public class MathBean {private String compare;public String isCompare() {return compare;}public MathBean(String compare) {this.compare = compare;}public void setCompare(String compare) {this.compare = compare;}@Overridepublic String toString() {return "MathBean{" +"compare=" + compare +'}';}
}
<?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:c="http://www.springframework.org/schema/c"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="MathBean" class="com.powernode.entity.MathBean" c:compare="sdasd"></bean></beans>
    @org.junit.Testpublic void CSetType(){ApplicationContext beans = new ClassPathXmlApplicationContext("beans-C-type.xml");MathBean mathBean = (MathBean) beans.getBean("MathBean");System.out.println(mathBean);// MathBean{compare=sdasd}}

util命名空间

util命名空间的作用就是** 配置复用**。
  1. 使用时需要配置头部文件:
    • xmlns:util=“http://www.springframework.org/schema/util”
    • http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
  2. 标签名 —— util:类型

<?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:util="http://www.springframework.org/schema/util"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"><util:properties id="prop"><prop key="driver">com.mysql.cj.jdbc.Driver</prop><prop key="url">jdbc:mysql://localhost:3306/spring</prop><prop key="username">root</prop><prop key="password">root</prop></util:properties><bean id="dataSourceOne" class="com.powernode.entity.MyDataSource"><property name="properties" ref="prop"></property></bean><bean id="dataSourceTwo" class="com.powernode.entity.MyDataSource"><property name="properties" ref="prop"></property></bean>
</beans>
@org.junit.Test
public void utilTest(){ApplicationContext beans = new ClassPathXmlApplicationContext("beans-util.xml");MyDataSource myDataSource1 = (MyDataSource) beans.getBean("dataSourceOne");System.out.println(myDataSource1);// MyDataSource{properties={password=root, driver=com.mysql.cj.jdbc.Driver, url=jdbc:mysql://localhost:3306/spring, username=root}}MyDataSource myDataSource2 = (MyDataSource) beans.getBean("dataSourceTwo");System.out.println(myDataSource2);// MyDataSource{properties={password=root, driver=com.mysql.cj.jdbc.Driver, url=jdbc:mysql://localhost:3306/spring, username=root}}}

基于XML的自动装配

基于名称的自动装配
```java package com.powernode.Service;

import com.powernode.Dao.UserDao;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**

  • @Author:

  • @Description: TODO

  • @DateTime: 2024/9/19 15:19
    */
    public class UserServiceImpl implements UserService{

    private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);

    public UserDao aaa;

    public void setAaa(UserDao userDao){
    this.userDao = userDao;
    }

    @Override
    public void add() {
    logger.info(“add():userDao:{}”, userDao);
    userDao.add();
    }

    @Override
    public void update() {
    logger.info(“update():userDao:{}”, userDao);
    userDao.update();
    }
    }


```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"><!--根据名字进行自动装配--><!--注意:自动装配也是基于set方式实现的。--><bean id="userService" class="com.powernode.Service.UserServiceImpl" autowire="byName"/><bean id="aaa" class="com.powernode.Dao.UserDaoImpl"/>
</beans>
@org.junit.Test
public void byNameTest(){ApplicationContext beans = new ClassPathXmlApplicationContext("spring-autowire.xml");UserService userService = (UserService) beans.getBean("userService");userService.add();userService.update();
}

✅UserService Bean中需要添加 **<font style="color:#DF2A3F;">autowire="byName"</font>**,表示进行名称装配

✅UserService类中有一个UserDao属性,而UserDao属性的名字是aaa,对应的set方法是setAaa(),正好和UserDao Bean的id是一样的。这就是根据名称自动装配。

基于类型的自动装配
```java package com.powernode.Dao;

public class AccountDao {
public void insert(){
System.out.println(“正在保存账户信息”);
}
}


```java
package com.powernode.Service;import com.powernode.Dao.AccountDao;public class AccountService {private AccountDao accountDao;public void setAccountDao(AccountDao accountDao) {this.accountDao = accountDao;}public void save(){accountDao.insert();}
}
<?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"><!--byType表示根据类型自动装配--><!--自动装配是基于set方法的--><!--根据类型进行自动装配的时候,在有效的配置文件当中,某种类型的实例只能有一个。--><bean id="accountService" class="com.powernode.Service.AccountService"autowire="byType"/><bean class="com.powernode.Dao.AccountDao"/>
</beans>
    @org.junit.Testpublic void byNameTest(){ApplicationContext beans = new ClassPathXmlApplicationContext("spring-autowire.xml");UserService userService = (UserService) beans.getBean("userService");userService.add();userService.update();AccountService accountService = (AccountService) beans.getBean("accountService");accountService.save();}

如果根据类型装配(byType),在装配的时候都是基于set方法的,所以set方法是必须要提供的。当byType进行自动装配的时候,配置文件中某种类型的Bean必须是唯一的,不能出现多个。

Spring引入外部属性文件

1、引入context命名空间

2、使用标签context

3、取值

以数据库配置为例,在实际开发中,数据库配置一般都是存放在properties/yaml文件中的,这样用户修改起来会更加的方便。当然可以。

第一步:实现一个数据源类,提供相关属性

package com.powernode.entity;import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger;/*** @Author: * @Description: TODO* @DateTime: 2024/9/24 11:09*/
public class MyJdbcSource implements DataSource {private String driver;private String url;private String username;private String password;@Overridepublic String toString() {return "MyJdbcSource{" +"driver='" + driver + '\'' +", url='" + url + '\'' +", username='" + username + '\'' +", password='" + password + '\'' +'}';}public String getDriver() {return driver;}public void setDriver(String driver) {this.driver = driver;}public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}@Overridepublic Connection getConnection() throws SQLException {return null;}@Overridepublic Connection getConnection(String username, String password) throws SQLException {return null;}@Overridepublic PrintWriter getLogWriter() throws SQLException {return null;}@Overridepublic void setLogWriter(PrintWriter out) throws SQLException {}@Overridepublic void setLoginTimeout(int seconds) throws SQLException {}@Overridepublic int getLoginTimeout() throws SQLException {return 0;}@Overridepublic Logger getParentLogger() throws SQLFeatureNotSupportedException {return null;}@Overridepublic <T> T unwrap(Class<T> iface) throws SQLException {return null;}@Overridepublic boolean isWrapperFor(Class<?> iface) throws SQLException {return false;}
}

第二步:在类路径下新建dataSource.properties文件,并配置信息

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring
jdbc.username=root
jdbc.password=root

第三步:在Spring配置文件中引入context命名空间

<?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.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"></beans>

第四步:在spring中配置使用dataSource.properties文件

<?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.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!--引入properties文件:第一步:引入context命名空间第二步:使用context:property-placeholder的location属性来指定属性配置文件的路径location默认从类的根路径下开始加载资源。--><context:property-placeholder location="dataSource.properties"/><!--配置数据源--><bean id="dataSource" class="com.powernode.entity.MyJdbcSource"><property name="driver" value="${jdbc.driver}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></bean>
</beans>

第五步:测试

@org.junit.Test
public void propertiesTest(){ApplicationContext beans = new ClassPathXmlApplicationContext("beans-dataSource.xml");MyJdbcSource jdbcSource = (MyJdbcSource) beans.getBean("dataSource");System.out.println(jdbcSource);// MyJdbcSource{driver='com.mysql.cj.jdbc.Driver', url='jdbc:mysql://localhost:3306/spring', username='root', password='root'}}

注意点:${}默认会先加载windows里面的环境变量

这也是大多数数据库配置源都是采用xxx.xxx.jdbc.driver的形式,因为xml在解析${}能够找到对应的键值内容

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/442774.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

(14)MATLAB莱斯(Rician)衰落信道仿真4

文章目录 前言一、改写莱斯分布概率密度函数的理论值二、仿真代码三、仿真结果总结 前言 本文通过将接收信号总功率设置为1&#xff0c;重写了莱斯衰落信道上接收信号幅度的理论PDF式。然后用MATLAB代码生成了在具有不同莱斯因子K的Ricean平坦衰落信道下接收到的信号样本&…

理解计算机系统_程序的机器级表示(二):寄存器,操作数,数据传送,程序栈

前言 以<深入理解计算机系统>(以下称“本书”)内容为基础&#xff0c;对程序的整个过程进行梳理。本书内容对整个计算机系统做了系统性导引,每部分内容都是单独的一门课.学习深度根据自己需要来定 引入 本书第三章&#xff1a;程序的机器级表示内容的理解,这一章内容以汇…

nginx代理,nginx301跳转,nginx地址重写

ngin代理 假如你的地址是:http://192.168.1.2:8282 你的域名是:www.jjycheng.com 你想访问域名www.jjycheng.com时,实际请求的地址是http://192.168.1.2:8282,但浏览器上的地址不变。 此时,你用到的技术就是请求代理 代理.conf配置 http {server {listen 80; server_na…

看门狗电路设计

看门狗电路设计 看门狗是什么应用架构图TPV6823芯片功能硬件时序图为什么要一般是要保持200个毫秒左右的这种低电平的时间看门狗电路实际应用与条件 看门狗是什么 硬件看门狗芯片&#xff0c;Watch DogTimer&#xff0c;可用于受到电气噪音、电源故障、静电放电等影响(造成软件…

LabVIEW混合控制器质量检测

随着工业自动化水平的提高&#xff0c;对控制器的精度、稳定性、可靠性要求也在不断上升。特别是在工程机械、自动化生产、风力发电等领域&#xff0c;传统的质量检测方法已无法满足现代工业的高要求。因此&#xff0c;开发一套自动化、精确、可扩展的混合控制器质量检测平台成…

怎么编辑图片?这5款工具教你快速编辑

怎么编辑图片&#xff1f;编辑图片是一项既具创意又实用的技能&#xff0c;它不仅能够提升图片的视觉效果&#xff0c;增强信息的传达力&#xff0c;还能激发无限的创作灵感。通过编辑图片&#xff0c;我们可以轻松调整色彩、添加文字、裁剪构图&#xff0c;甚至创造出令人惊叹…

《Linux从小白到高手》理论篇:Linux的系统环境管理

List item 值此国庆佳节&#xff0c;深宅家中&#xff0c;闲来无事&#xff0c;就多写几篇博文。本篇详细深入介绍Linux的系统环境管理。 环境变量 linux系统下&#xff0c;如果你下载并安装了应用程序&#xff0c;很有可能在键入它的名称时出现“command not found”的提示…

【Redis】Redis线程模型

目录 1. Redis 是单线程的&#xff0c;还是多线程的&#xff1f;2. Redis单线程模式是怎么样的&#xff1f;Redis 单线程模式的优势Redis 单线程的局限性Redis 单线程的优化策略 3. Redis采用单线程为什么还这么快4. Redis 6.0 之前为什么使用单线程&#xff1f;5. Redis 6.0 之…

10.1 10.3 图DFS 中等 207 Course Schedule 210 Course Schedule Ⅱ

207 Course Schedule class Solution { public:bool hasCycle(int course ,unordered_map<int,vector<int>>& graph,vector<int>& visitStatus){//正在访问的结点再次被访问&#xff0c;存在环if(visitStatus[course] 1)return true;//该结点已经被…

仪器校准机构提供了资质证明,就能够代表目前的检测能力吗?

最近的一次公司审核打破了我对仪器校准机构能力认证这一独特理论的认识。换句话说&#xff0c;最近参加了公司的质量整合审核&#xff0c;其中之一就是仪器校准机构检测能力审核。根据我平时的经验&#xff0c;我给审核老师提供了CNAS和客户等一系列资质证书&#xff0c;以证明…

PMP--冲刺题--解题--91-100

文章目录 11.风险管理--4.实施定量风险分析--题干场景中提到了“专家”&#xff0c;同时即将开始“量化风险”&#xff0c;因此对应的就是“定量风险分析”中的“专家判断”技术。项目经理应先征求各位专家们的意见&#xff0c;以获取最佳的量化风险实施方案。谋定而后动91、 […

芯片复位电路-RC复位

芯片复位电路-RC复位 MAX809专门的上电复位芯片使用注意芯片间级联复位 看门狗复位注意事项 MAX809专门的上电复位芯片 可以看到这里VTH这个电压值一般是你你电复位芯片供电的90%左右&#xff0c;比如说5V&#xff0c;那这里可能是4.5V。 使用注意 A.复位输出引脚要加上拉电阻…

解决跨域问题

第一种 让后端解决 第二种 通过代理来解决 首先可以先搭建后端接口 解决则参照vue-cli官网 首先新建一个vue.config.js文件 然后在项目的根目录新建两个文件夹 开发环境和生产环境 然后可以使用环境变量 系统会自动识别你是生产环境还是开发环境 然后在封装的axios中配…

【Qt】控件概述 (1)—— Widget属性

控件概述 1. QWidget核心属性1.1核心属性概述1.2 enable1.3 geometry——窗口坐标1.4 window frame的影响1.4 windowTitle——窗口标题1.5 windowIcon——窗口图标1.6 windowOpacity——透明度设置1.7 cursor——光标设置1.8 font——字体设置1.9 toolTip——鼠标悬停提示设置1…

Puppeteer自动化:使用JavaScript定制PDF下载

引言 在现代的Web开发中&#xff0c;自动化已经成为提高效率和减少重复劳动的重要手段。Puppeteer 是一个强大的Node.js库&#xff0c;提供了对无头Chrome或Chromium的控制&#xff0c;可以用于生成网页快照、抓取数据、自动化测试等任务。其中&#xff0c;生成PDF文件是一个常…

cnn突破八(两层卷积核bpnet网络扩展)

cnn突破七中x【&#xff1f;】怎么求&#xff1f;我们举个例子&#xff1a; 接着cnn突破七&#xff1a; hicnn【】来自temphicnn【】2*2最大池化&#xff1a; temphicnn[0]x[i0,j0,5*5方阵]*w1cnn[0-24]&#xff0c; hicnn是5*5的&#xff0c;temphicnn是10*10的&#xff0…

git clone 私有仓库时出现错误 Authentication failed for :xxxxxx

错误信息 remote: Support for password authentication was removed on August 13, 2021. remote: Please see https://docs.github.com/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended…

音频剪辑在线工具 —— 让声音更精彩

你是否曾梦想过拥有自己的声音创作空间&#xff0c;却苦于复杂的音频编辑软件&#xff1f;接下来&#xff0c;让我们一同揭开这些音频剪辑在线工具的神秘面纱&#xff0c;看看它们如何帮助你实现从录音到发布的无缝衔接。 1.福昕音频剪辑 链接直达>>https://www.foxits…

Windows系统编程(三)线程并发

进程与线程 进程&#xff1a;直观的说就是任务管理器中各种正在运行的程序。对于操作系统来说&#xff0c;进程仅仅是一个数据结构&#xff0c;并不会真实的执行代码 线程&#xff1a;通常被称作但并不真的是轻量级进程或实际工作中的进程&#xff0c;它会真实的执行代码。每…

Qwen变体新成员加一,英伟达训练 NVLM-D-72B 视觉大模型

今天&#xff08;2024 年 9 月 17 日&#xff09;&#xff0c;我们推出了前沿级多模态大语言模型&#xff08;LLM&#xff09;系列 NVLM 1.0&#xff0c;它在视觉语言任务上取得了最先进的结果&#xff0c;可与领先的专有模型&#xff08;如 GPT-4o&#xff09;和开放存取模型&…