MIKU MOE

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理论

  1. UserDao接口

  2. UserDaolmpl实现类

  3. UserService 业务接口

  4. 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创建对象方式

  1. 使用无参构造创建对象 (默认)

  2. 使用有参构造 -- 有三种方法

    复制代码
     <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);

 

  1. 单例模式 (Spring默认机制) (共享一个对象)

     <bean id="user2" class="com.study.pojo.User" c:name="-name2-" c:age="18" scope="singleton"/>

     

  2. 原型模式 scope="prototype" 每次从容器get都会产生一个新对象

  3. 其余的request、session、application 只能在Web开发使用

 

7. Bean的自动装配

  • 自动装配是Spring满足bean依赖一种方式!

  • Spring会在上下文中自动寻找,并自动给bean装配属性!

在Spring中有三种装配的方式

  1. 在xml中显示的配置

  2. 在java中显示配置

  3. 隐式的自动装配 (重要)

 <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可以省略

  注解实现自动装配

要使用注解须知:

  1. 导入约束 context约束

  2. 配置注解的支持

    复制代码
     <?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());
复制代码

 

posted @   miku_moe  阅读(40)  评论(0编辑  收藏  举报
编辑推荐:
· 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)
点击右上角即可分享
微信分享提示