SSM_Spring_IOC_配置_注解
SSM_Spring
1. Spring
1. 简介
-
Spring:春天----->给软件行业带来了春天!
-
2002,首次推出了Spring框架的雏形: interface21框架
-
Spring框架即以interface21框架为基础,经过重新设计;并不断丰富其内涵,于2004年3月24日,发布了1.0正式版。
-
Rod Johnson , Spring Framework创始人,著名作者。很难想象Rod Johnson的学历,真的让好多人大吃一惊,他是悉尼大学的博士,然而他的专业不是计算机,而是音乐学。
-
spring理念:使现有的技术更加容易使用,本身是一个大杂烩,整合了现有的技术框架!
-
解决企业应用开发的复杂性
-
使用基本的JavaBean代替EJB
-
-
SSH : Struct2+ Spring + Hibernate!
-
SSM : SpringMvc + Spring + Mybatis !
官网 : https://spring.io/projects/spring-framework
官方下载地址 : https://repo.spring.io/ui/native/release/org/springframework/spring
Github : https://github.com/spring-projects/spring-framework
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.9</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.3.9</version> </dependency>
2. 优点
-
Spring是一个开源的免费的框架(容器)!
-
Spring是一个轻量级的,非入侵式的框架!
-
控制反转(IOC) ,面向切面编程(AOP) (重点)
-
支持事务的处理,对框架整合的支持
Spring就是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架
3. 组成
4. 扩展
在Spring的官网有这个介绍:现代化的Java开发!说白就是基于Spring的开发
-
Spring Boot
-
一个快速开发的脚手架。
-
基于SpringBoot可以快速的开发单个微服务。
-
约定大于配置
-
-
Spring Cloud
-
SpringCloud是基于SpringBoot实现的。
-
因为现在大多数公司都在使用SpringBoot进行快速开发,学习SpringBoot的前提,需要完全掌握Spring及SpringMvC!承上启下!
弊端 : 发展了太久之后,违背了原来的理念 ! 配置十分繁琐
2. IOC理论
-
UserDao接口
-
UserDaolmpl实现类
-
UserService 业务接口
-
UserServicelmpl业务实现类
在我们之前的业务中,用户的需求可能会影响我们原来的代码,我们需要根据用户的需求去修改原代码!如果程序代码量十分大,修改一次的成本代价十分昂贵!
public class UserServiceImpl implements UserService { //如果需要实现不同的DaoImpl就需要修改业务层代码 private UserDao userDao = new UserDaoImpl(); public void getUser(){ userDao.getUser(); } }
//用户实际调用的是业务层,dao层他们不需要接触!
UserService userService = new UserServiceImpl();
userService.getUser();
-
之前,程序是主动创建对象!控制权在程序猿手上!
修改
public class UserServiceImpl implements UserService { private UserDao userDao; //利用set进行动态实现值的注入! public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void getUser(){ userDao.getUser(); } }
//实现根据用户层选择方法 UserService userService = new UserServiceImpl(); ((UserServiceImpl) userService).setUserDao(new UserDaoImpl()); userService.getUser();
-
使用了set注入后,程序不再具有主动性,而是变成了被动的接受对象!
这种思想,从本质上解决了问题,我们程序猿不用再去管理对象的创建了。系统的耦合性大大降低~,可以更加专注的在业务的实现上!这是IOC的原型!
本质
控制反转loC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现loC的一种方法,也有人认为DI只是loC的另一种说法。没有loC的程序中,我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。
loC是Spring框架的核心内容,使用多种方式完美的实现了loC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置实现loC。
Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从loc容器中取出需要的对象。
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是loC容器,其实现方法是依赖注入(Dependency Injection,Dl).
3. HelloSpring
-
Hello 对象是谁创建的? -- hello对象是由Spring创建的
-
Hello对象的属性是怎么设置的? -- hello对象的属性是由Spring容器设置的
-
这个过程就叫做控制反转
-
控制 : 谁来控制对象的创建,传统应用程序的对象是由程序本身控制创建的,使用Spring后,对象是由Spring来创建的.
-
反转 : 程序本身不创建对象,而变成被动的接收对象
-
依赖注入 : 就是利用set方法来进行注入的
-
IOC是一种编程思想,由主动的编程变成被动的接收.
-
可以通过newClassPathXmlApplicationContext去浏览一下底层源码.
-
到了现在,我们彻底不用再程序中去改动了,要实现不同的操作,只需要在xml配置文件中进行修改,所谓的loC,一句话搞定:对象由Spring来创建,管理,装配!
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="UTF8"?> <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 Hello hello = new Hello() id:变量名 class:new的对象 property:相当于给对象中的属性设置一个值 --> <bean id="Hello" class="com.study.pojo.Hello"> <!-- ref: 引入Spring容器中创建好的对象 value: 具体的值,基本数据类型! --> <property name="str" value="Spring"/> </bean> </beans>
测试类
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创建对象方式
-
使用无参构造创建对象 (默认)
-
使用有参构造 -- 有三种方法
<bean id="User" class="com.study.pojo.User"> <property name="name" value="无参构造"/> </bean> <!--通过有参构造--> <!--<bean id="User2" class="com.study.pojo.User2"> <constructor-arg index="0" value="有参(通过下标)"/> </bean>--> <!--<bean id="User2" class="com.study.pojo.User2"> <constructor-arg type="java.lang.String" value="有参(通过类型)-不推荐!"/> </bean>--> <bean id="User2" class="com.study.pojo.User2"> <constructor-arg name="name" value="有参(通过参数名)"/> </bean>
总结:在配置文件加载的时候,容器中管理的对象就已经初始化了!
5. Spring配置
别名
<alias name="user" alias="userNew"/ >
Bean配置
<!-- id : bean的唯一标识符,也就是相当于我们学的对象名 cLass : bean对象所对应的全限定名:包名+类型 name : 也是别名,而且name可以同时取多个别名,";"","" "都可以分割 --> <bean id="userT" class="com.kuang.pojo.UserT" name="user2,u2"> <property name="name" value="Java"/> </bean>
import
这个import,一般用于团队开发使用,他可以将多个配置文件,导入合并为一个
假设,现在项目中有多个人开发,这三个人复制不同的类开发,不同的类需要注册在不同的bean中,我们可以利用import将所有人的beans.xml合并为一个总的!
使用的时候,直接使用总的配置就可以了 -- applicationContext.XML
<import resource= "beans1.xml"/>
6. 依赖注入 DI
构造器注入
讲过
Set方式注入 ***
-
依赖注入:set注入!
-
依赖: bean对象的创建依赖于容器!
-
注入: bean对象中的所有属性,由容器来注入!
-
实体类
//Address private String address; //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; @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", address=" + address.toString() + ", books=" + Arrays.toString(books) + ", hobbys=" + hobbys + ", card=" + card + ", games=" + games + ", wife='" + wife + '\'' + ", info=" + info + '}'; }
beans.xml
<?xml version="1.0" encoding="UTF8"?> <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="address" class="com.study.pojo.Address"> <property name="address" value="-Address-"/> </bean> <bean id="student" class="com.study.pojo.Student"> <!-- 1. 普通值注入 - value--> <property name="name" value="-name-"/> <!-- 2. Bean注入 - ref--> <property name="address" ref="address"/> <!-- 3. 数组注入 - ref--> <property name="books"> <array> <value>西游记</value> <value>红楼梦</value> </array> </property> <!-- 4. List--> <property name="hobbys"> <list> <value>电影</value> <value>听歌</value> </list> </property> <!-- 5. Map--> <property name="card"> <map> <entry key="身份证" value="1231xxxxxxx"/> <entry key="银行卡" value="4202xxxxxxx"/> </map> </property> <!-- 6. Set--> <property name="games"> <set> <value>game1</value> <value>game2</value> </set> </property> <!-- 7. null--> <property name="wife"> <null/> </property> <!-- 8. Properties--> <property name="info"> <props> <prop key="学号">202020</prop> <prop key="姓名">XXX</prop> </props> </property> </bean> </beans>
测试类
public class Test { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); Student student = (Student) context.getBean("student"); System.out.println(student.toString()); } }
拓展方式注入
我们可以使用p命令空间和c命令空间进行注入
P命名空间: 可以直接注入属性的值 property
<!--p命名空间注入,可以直接注入属性的值:property--> xmlns:p="http://www.springframework.org/schema/p" <bean id="user" class="com.study.pojo.User" p:name="-name1-" p:age="18"/> //显示的定义不需要强转 User user = context.getBean("user",User.class);
C命名空间: 通过构造器注入 construct-args
xmlns:c="http://www.springframework.org/schema/c" <!--需要有有参构造器--> <bean id="user2" class="com.study.pojo.User" c:name="-name2-" c:age="18"/>
-
不能直接使用需要导入xml约束
Bean Scopes(作用域)
User user1 = context.getBean("user",User.class); User user2 = context.getBean("user",User.class);
-
单例模式 (Spring默认机制) (共享一个对象)
<bean id="user2" class="com.study.pojo.User" c:name="-name2-" c:age="18" scope="singleton"/>
-
原型模式 scope="prototype" 每次从容器get都会产生一个新对象
-
其余的request、session、application 只能在Web开发使用
7. Bean的自动装配
-
自动装配是Spring满足bean依赖一种方式!
-
Spring会在上下文中自动寻找,并自动给bean装配属性!
在Spring中有三种装配的方式
-
在xml中显示的配置
-
在java中显示配置
-
隐式的自动装配 (重要)
<bean id="cat" class="com.study.pojo.cat"/> <bean id="dog" class="com.study.pojo.Dog"/> <bean id="people" class="com.study.pojo.People"> <property name="name" value="-name-"/> <property name="dog" ref="dog"/> <property name="cat" ref="cat"/> </bean>
autaowire
<!--byName:会自动在容器上下文中查找,和自己对象set手法后面的值对应的beanid--> <bean id="cat" class="com.study.pojo.cat"/> <bean id="dog" class="com.study.pojo.Dog"/> <bean id="people" class="com.study.pojo.People" autowire="byName"> <property name="name" value="-name-"/> </bean> <!--byType:会自动在容器上下文中查找,和自己对象属性类型相同的bean--> <bean class="com.study.pojo.cat"/> <bean class="com.study.pojo.Dog"/> <bean id="people" class="com.study.pojo.People" autowire="byType"> <property name="name" value="-name-"/> </bean>
byname,需要保证所有bean的id唯一,并且这个bean需要和自动注入的属性的set方法的值一致!
bytype,需要保证所有bean的class唯一,并且这个bean需要和自动注入的属性的类型一致,id可以省略
注解实现自动装配
要使用注解须知:
-
导入约束 context约束
-
配置注解的支持
<?xml version="1.0" encoding="UTF8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="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 (最常用)
-
直接在属性上使用即可!也可以在set方式上使用!
-
使用Autowired我们可以不用编写Set方法了,前提是你这个自动装配的属性在IOC (Spring)容器中存在,且符合名字byname!
@Qualifier
<bean id="cat" class="com.study.pojo.cat"/> <bean id="cat222" class="com.study.pojo.cat"/> <bean id="dog" class="com.study.pojo.Dog"/> <bean id="dog222" class="com.study.pojo.Dog"/> <bean id="people" class="com.study.pojo.People"/> @Autowired private Cat cat; @Autowired @Qualifier(value="dog222") private Dog dog; private S tring name;
如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解【@Autowired】完成的时候、我们可以使用@Qualifier(value="xxx")去配置@Autowired的使用,指定一个唯一的bean对象注入!
@Nullable
-
字段标记了这个注解说明这个字段可以为null
//如果显示定义了Autowired的required属性为false,说明这个对象可以为null,否则不允许为空@Autowired(required = false)
private Cat cat;
@Resource
-
先查找名字,如果名字不匹配,查找类型,不唯一或不存在则报错
-
可以带参数@Resource(name="cat222")
小结:
@Resource和@Autowired的区别:
-
都是用来自动装配的,都可以放在属性字段上
-
@Autowired 通过byType的方式实现,而且必须要求这个对象存在!【常用】
-
@Resource默认通过byname的方式实现,如果找不到名字,则通过byType实现!如果两个都找不到的情况下,就报错!【常用】
-
执行顺序不同:@Autowired通过byType的方式实现,@Resource通过byname的方式实现
-
@Autowired : 自动装配通过类型,名字
-
如果不能唯一自动装配上属性,通过@Qualifier(value="xxx")
-
-
@Resource : 自动装配通过名字,类型
8. 使用注解开发
在Spring4之后,要使用注解必需要保证aop的包导入了(spring-web-mvc包括了aop)
-
bean -- @Component
<!--指定要扫描的包,这个包下的注解就会生效--> <context:component-scan base-package="com.study.pojo"/> <!--注解驱动--> <context:annotation-config/>
-
属性如何注入 -- @Value("xxx")
//等价于<bean id="user" class="com.study.pojo.User"/> //@Component 组例 (名称默认为类的小写user) @Component public class User { //相当于<property name="name" value="-name-"/> @Value("") public String name; // @Value("-name-") 也可以注入 public void setName(String name){ this.name = name; } }
-
衍生的注解
@Component有几个衍生注解,我们在web开发中,会按照mvc三层架构分层
-
dao 【@Repository】
-
service 【@service】
-
controller 【@Controller】
功能相同,都代表将某个类注册到Spring,装配Bean
-
-
自动装配置
-
作用域
-
@Scope("prototype")
-
-
小结
-
xml 与注解:
-
xml更加万能,适用于任何场合!维护简单方便。
-
注解不是自己类使用不了,维护相对复杂!
-
-
xml与注解最佳实践:
-
xml用来管理bean;
-
注解只负责完成属性的注入;
-
-
我们在使用的过程中,只需要注意一个问题:必须让注解生效,就需要开启注解的支持
<context:component-scan base-package="com.study" /> <context: annotation-config/>
-
9. 使用Java方式配置Spring
我们现在要完全不使用Spring的xml配置了,全权交给Java来做!
JavaConfig 是Spring的一个子项目,在Spring 4之后,它成为了一个核心功能!
//这个也会Spring容器托管,注册到容器中,因为他本来就是一个@Component //Configuration代表这是一个配置类,就和我们之前看的beans.xmL @Configuration @ComponentScan("com.study.pojo") //@Import(Config2.c1ass) 引入其它java配置 public class Config { //注册一个bean,就相当于我们之前写的一个bean标签 //这个方法的名字,就相当于bean标签中的id国性 //这个方法的返回值,就相当于bean标签中的cLass属性@Bean public User getUser() { return new User();//就是返回要注入到bean的对象! } } public class MyTest { public static void main(String[] args) { //如果完全使用了配置类方式去傲,我们就只能通过AnnotationConfig上下文来获取容器,通过配置类的class对象加载! ApplicationContext context = new AnnotationConfigApplicationContext(Config.class); User getUser = (User) context.getBean("getUser"); System.out.print1n(getUser.getName());
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)