Spring5
1.简介
1.1简介和包
Spring就是一个轻量级的控制反转(I0C)和面向切面编程(AOP)的框架!
目的:解决企业应用开发的复杂性
功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能
范围:任何Java应用
-
SSH : Sturct2 + Spring + Hibernate
-
SSM: SpringMVC + Spring + Mybatis
包
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>6.2.9</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>6.2.9</version> </dependency>
1.2优点
-
Spring 是一个开源的免费的框架(容器)!
-
Spring 是一个轻量级的、非入侵式的框架!
-
控制反转(IOC),面向切面编程(AOP)!
-
支持事务的处理,对框架整合的支持!
2.IOC理论推导
1.UserDao 接口
2.UserDaoImpl 实现类
3.UserService 业务接口
4.UserServiceImpl 业务实现类
IOC本质
控制反转loC(inversion of control),是一种设计思想,DI(依赖注入)是实现loC的一种方法,也有人认为D!只是1oC的另一种说法。没有!0C的程序中,我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是loC容器,其实现方法是依赖注入(DependencyInjection,Dl)。
3.HelloSpring
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 使用Spring来创建对象,在Spring这些都成为Bean--> <bean id="hello" class="com.lyj.pojo.Hello"> <property name="str" value="Spring"></property> </bean> </beans>
有xml就必须要有这个
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");
实体类
package com.lyj.pojo; public class Hello { private String str; public String getStr() { return str; } public void setStr(String str) { this.str = str; } @Override public String toString() { return "Hello{" + "str='" + str + '\'' + '}'; } }
beans.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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 使用Spring来创建对象,在Spring这些都成为Bean--> <!-- 类型 变量名= new 类型();--> <!-- Hello hello = new Hello();--> <!-- id = 变量名--> <!-- class = new 的对象--> <!-- property = 相当于给对象中的属性设置一个值--> <bean id="hello" class="com.lyj.pojo.Hello"> <property name="str" value="Spring66666666666666666666666666"></property> </bean> </beans>
测试
import com.lyj.pojo.Hello; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MyTest { public static void main(String[] args) { //获取Spring的上下文对象 ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); //我们的对象现在都在Spring中的管理了,我们要使用,直接去里面取出来就可以 Hello hello = (Hello) context.getBean("hello"); System.out.println(hello.toString()); } }
4.IOC创建对象的方式
1.使用无参构造创建对象,默认
2.使用有参构造构建对象
-
下标赋值
<!-- 第一种下标赋值--> <bean id="user" class="com.lyj.pojo.User"> <constructor-arg index="0" value="12113"/> </bean>
-
类型,不建议
<!-- 第二种类型赋值,不建议--> <bean id="user" class="com.lyj.pojo.User"> <constructor-arg type="java.lang.String" value="65465644"/> </bean>
-
参数名
<!-- 第三种,直接通过参数名来设置--> <bean id="user" class="com.lyj.pojo.User"> <constructor-arg name="name" value="79879798"/> </bean>
总结:在配置文件加载的时候,容器中管理的对象就已经初始化了!
5.Spring配置
5.1别名
<alias name="user" alias="newnewnewUser"/>
5.2Bean的配置
<!-- id : bean 的唯一标识符,也就是相当于我们学的对象名 class : bean 对象所对应的全限定名 : 包名 + 类型 name : 也是别名,而且name可以同时取多个别名,可以用空格,逗号,斜线分割 --> <bean id="userT" class="com.kuang.pojo.UserT" name="user2 u2,u3/u4"> </bean>
5.3import
一般用于团队开发使用,可以将多个配置文件,导入合并为一个
假设,现在项目中有多个人开发,这三个人复制不同的类开发,不同的类需要注册在不同的bean中,我们可以利用import将所有人的beans.xml合并为一个总的!
张三
李四
王五
applicationContext.xml
<import resource="beans.xml"/> <import resource="beans2.xml"/> <import resource="beans3.xml"/>
使用的时候,直接使用总的配置就可以了
6. 依赖注入
6.1构造器注入
在上面4.IOC创建对象的方式
6.2Set方式注入(重点)
依赖注入:Set 注入!
-
依赖:bean 对象的创建依赖于容器!
-
注入:bean 对象中的所有属性,由容器来注入!
【环境搭建】
-
复杂类型
package com.lyj.pojo; public class Address { private String address; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
-
真实测试对象
package com.lyj.pojo; import java.util.*; public class Student { private String name; private Address address; private String[] books; private List<String> hobbys; private Map<String,String> card; private Set<String> games; private String wife; private Properties info; public String getName() { return name; } public void setName(String name) { this.name = name; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } public String[] getBooks() { return books; } public void setBooks(String[] books) { this.books = books; } public List<String> getHobbys() { return hobbys; } public void setHobbys(List<String> hobbys) { this.hobbys = hobbys; } public Map<String, String> getCard() { return card; } public void setCard(Map<String, String> card) { this.card = card; } public Set<String> getGames() { return games; } public void setGames(Set<String> games) { this.games = games; } public String getWife() { return wife; } public void setWife(String wife) { this.wife = wife; } public Properties getInfo() { return info; } public void setInfo(Properties info) { this.info = info; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", address=" + address + ", books=" + Arrays.toString(books) + ", hobbys=" + hobbys + ", card=" + card + ", games=" + games + ", wife='" + wife + '\'' + ", info=" + info + '}'; } }
-
Beans.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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean name="student" class="com.lyj.pojo.Student"> <!-- 第一种普通值注入,直接使用values--> <property name="name" value="张三"/> </bean> </beans>
-
测试
import com.lyj.pojo.Student; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Mytest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); Student student = (Student) context.getBean("student"); System.out.println(student.getName()); } }
6.2.1完善注入信息
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean name="address" class="com.lyj.pojo.Address"> <property name="address" value="地球"></property> </bean> <bean name="student" class="com.lyj.pojo.Student"> <!-- 第一种 普通值注入,使用values--> <property name="name" value="张三"/> <!-- 第二种 Bean注入,使用ref--> <property name="address" ref="address"/> <!-- 第三种 数组注入--> <property name="books"> <array> <value>红楼梦</value> <value>西游记</value> </array> </property> <!-- List注入--> <property name="hobbys"> <list> <value>爱好1</value> <value>爱好2</value> </list> </property> <!-- Map注入--> <property name="card"> <map> <entry key="身份证" value="123123"/> <entry key="银行卡" value="654654"/> </map> </property> <!-- Set注入--> <property name="games"> <set> <value>游戏1</value> <value>游戏2</value> </set> </property> <!-- NULL注入--> <property name="wife"> <null/> </property> <!-- properties注入--> <property name="info"> <props> <prop key="学号">123123132</prop> <prop key="性别">男</prop> <prop key="姓名">张三</prop> </props> </property> </bean> </beans>
6.3拓展方式注入
6.3.1 p命名空间注入
对应Set
<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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- p命名空间注入,可以直接注入属性的值:property--> <bean id="user" class="com.lyj.pojo.User" p:name="张三" p:age="20"/> <!-- <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource"--> <!-- destroy-method="close"--> <!-- p:driverClassName="com.mysql.jdbc.Driver"--> <!-- p:url="jdbc:mysql://localhost:3306/mydb"--> <!-- p:username="root"--> <!-- p:password="misterkaoli"/>--> </beans>
import com.lyj.pojo.Student; import com.lyj.pojo.User; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Mytest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); Student student = (Student) context.getBean("student"); System.out.println(student.toString()); } @Test public void test2(){ ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml"); User user = (User)context.getBean("user"); //User user1 = context.getBean("user", User.class); System.out.println(user); } }
6.3.2 c命名空间注入
对应构造器
<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" xmlns:c="http://www.springframework.org/schema/c" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- p命名空间注入,可以直接注入属性的值:property--> <bean id="user1" class="com.lyj.pojo.User" p:name="张三" p:age="20"/> <!-- p命名空间注入,通过构造器注入:construct-args--> <bean id="user2" class="com.lyj.pojo.User" c:name="李四" c:age="30"/> <!-- <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource"--> <!-- destroy-method="close"--> <!-- p:driverClassName="com.mysql.jdbc.Driver"--> <!-- p:url="jdbc:mysql://localhost:3306/mydb"--> <!-- p:username="root"--> <!-- p:password="misterkaoli"/>--> </beans>
import com.lyj.pojo.Student; import com.lyj.pojo.User; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Mytest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); Student student = (Student) context.getBean("student"); System.out.println(student.toString()); } @Test public void test2(){ ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml"); User user = (User)context.getBean("user2"); //User user1 = context.getBean("user2", User.class); System.out.println(user); } }
注意点:p命名和c命名空间不能直接使用,需要导入xml约束!
xmlns:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c"
6.4Bean的作用域
1.单例模式(Spring默认机制)
<bean id="user1" class="com.lyj.pojo.User" p:name="张三" p:age="20" scope="singleton"/>
2.原型模式:每次从容器中get的时候,都会产生一个新对象
<bean id="user1" class="com.lyj.pojo.User" p:name="张三" p:age="20" scope="prototype"/>
3.其余的request,session,application,这些只能在web开发中使用到
7. Bean的自动装配
自动装配核心概念
-
自动装配是 Spring 满足 bean 依赖的一种方式
-
Spring 会在上下文中自动寻找,并自动给 bean 装配属性
Spring 装配的三种方式
-
在 xml 中显式配置
-
在 java 中显式配置
-
隐式的自动装配 bean
7.1测试
环境搭建:People,Dog,Cat
7.2 ByName自动装配
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="cat" class="com.kuang.pojo.Cat"/> <bean id="dog" class="com.kuang.pojo.Dog"/> <!-- byName:会自动在容器上下文中查找,和自己对象 set 方法后面的值对应的 beanid! --> <bean id="people" class="com.kuang.pojo.People" autowire="byName"> <property name="name" value="张三"/> </bean> </beans>
7.3ByType自动装配
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean class="com.kuang.pojo.Cat"/> <bean class="com.kuang.pojo.Dog"/> <!-- byType:会自动在容器上下文中查找,和自己对象 属性类型相同的 beanid! --> <bean id="people" class="com.kuang.pojo.People" autowire="byType"> <property name="name" value="张三"/> </bean> </beans>
小结:
-
pyname的时候,需要保证所有bean的id唯一,并且这个bean需要和自动注入的属性的set方法的值一致!
-
bytype的时候,需要保证所有bean的class唯一,并且这个bean需要和自动注入的属性的类型一致!
7.4 使用注解实现自动装配
使用注解:
1.导入约束
2.配置注解的支持:context:annotation-config/
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <context:annotation-config/> </beans>
@Autowired
直接在属性是使用即可,也可以咋iset方式上使用
使用Autowired外面可以不用编写Set方法,前提是自动装配的属性在IOC(Spring)容器中存在,且符合名字ByName
另外:
@Nullable 字段标记了这个注解,说明这个字段可以为null import org.springframework.lang.Nullable;导包 public People(@Nullable String name) { this.name = name; }
//如果显示定义了Autowired的required属性为false,说明这个对象可以为null,否则不允许为空 @Autowired(required= false) private Cat cat;
@Quelifier
指定一个
@Quelifier(value= "dog222") private Dog dog;
如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解【@Autowired】完成的时候、我们可以使用@Qualifier(value="xxx")去配置@Autowired的使用,指定一个唯一的bean对象注入!
@Resource注解
public class People{ @Resource(name = "cat2") private Cat cat; @Resource private Dog dog; }
小结:@Resource 和 @Autowired 的区别
-
相同点: 均用于自动装配,可直接标注在属性字段上实现依赖注入。
-
不同点:
-
@Autowired
:-
默认通过 byType(按类型) 方式匹配 Bean(若存在多个同类型 Bean,需结合
@Qualifier
按名称精准注入 ); -
要求依赖的对象必须存在(默认
required = true
),否则启动报错(常用场景下需确保依赖可用)。
-
-
@Resource
:-
默认通过 byName(按名称) 方式匹配 Bean(根据属性名 / 字段名查找容器中对应
id
的 Bean ); -
若按名称找不到匹配 Bean,会 fallback 到 byType(按类型) 查找;
-
若名称、类型均无匹配,才会报错(适配性更强,支持更灵活的注入逻辑 )。
-
-