java学习总结(六)Spring IOC

一、Spring框架介绍

Spring优点:

1、方便解耦,简化开发,IOC控制反转

Spring 就是一个大工厂,可以将所有对象创建和依赖关系维护交给Spring

2、AOP 编程的支持

Spring 提供面向切编程,可以方便的实现对序进行权限拦截、运监控等功能

3、声明式事务的支持(张三给李四转账,要么同时成功,要么同时失败)

只需要通过配置就可以完成对事务的管理,而无手动编程

4、方便集成各种优秀框架

Spring 不排斥各种优秀的开源框架,其内部提供了对各种优优秀框架的支持(如Struts,Mybatis,Hibernate)。

SSH SSM

二、IOC和DI

控制反转(Inversion on Control)IOC:对象的创建交给外部容器来完成(这里就是交给Spring容器),这就叫控制反转。

IOC:Spring就是一个大的内存容器(一块内存区域),三层架构里面上一层不需要再去new下一层对象,在上一层只需要写下一层的接口,new对象由Spring容器帮我们完成,各层直接向Spring容器要对象就可以。

复制代码
class StudentController{
    // 需要什么,就去创建什么(自己去new),这就叫"控制正转"(通俗一点就是自己控制new哪个对象)
    private IStudentService studentService = new StudentServiceImpl();
}

class StudentController{
     // 对象的创建交给别人去new(现在交给Spring容器new StudentServiceImpl(),new出来对方放在Spring容器),这就叫控制反转"IOC"
     private IStudentService studentService; 
    
     // 将Spring容器中new出来的对象通过set方法赋值给studentService,这个过程叫依赖注入:DI
     public void setStudentService(IStudentService studentService) {
             this.studentService = studentService;
     }
} 

依赖注入:Dependency injection (DI)

现在new这个对象不是由自己new,是由Spring容器帮我们new对象,现在要得到这个Spring容器new出来的对象,就要"依赖"Spring容器,"注入"Spring容器new出来的对象。

IOC和DI区别:

IOC:解决对象创建的问题(对象的创建交给别人)Inversion of Control。

DI:在创建完对象后,对象关系的处理就是依赖注入(通过set方法实现依赖注入)Dependency injection。

先有IOC(对象创建),再有DI(处理对象关系)

在三层架构中最终实现的效果是:在Controller不会出现Service层具体的实现类代码,只会看到Service层接口,Service层也不会出现Dao层具体实现类的代码,也只会看到Dao层的接口

四、Bean的属性: scope范围

1、singleton

是scope的默认值,单例模式,在Spring容器中只存在一个实例。

复制代码
public void test3() {
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    Student student1 = (Student) context.getBean("student");
    Student student2 = (Student) context.getBean("student");
    System.out.println(student1 == student2);// true
}

2、prototype

多例,会创建多个对象,每次去容器里面拿会创建一个新的实例

复制代码
<bean scope="prototype" name="student" class="com.situ.spring.pojo.Student"/>

public void test3() {
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    Student student1 = (Student) context.getBean("student");
    Student student2 = (Student) context.getBean("student");
    System.out.println(student1 == student2);// false
}

五、Spring属性注入方式

1、set方法注入

复制代码
<bean name="banji" class="com.situ.spring.pojo.Banji">
    <property name="id" value="1"/>
    <property name="name" value="Java2023"/>
</bean>
<bean name="student" class="com.situ.spring.pojo.Student">
    <!-- 值类型注入 -->
    <property name="id" value="1"/>
    <property name="name" value="张三"/>
    <property name="age" value="23"/>
    <property name="gender" value="男"/>
    <!-- ref:reference参考、引用
       引用类型的注入
    -->
    <property name="banji" ref="banji"/>
</bean>

2、构造方法注入

argument:参数

parameter:参数

复制代码
<bean name="banji" class="com.situ.spring.pojo.Banji">
    <constructor-arg name="id" value="1"/>
    <constructor-arg name="name" value="Java2023"/>
</bean>
<bean name="student" class="com.situ.spring.pojo.Student">
    <constructor-arg name="id" value="1"/>
    <constructor-arg name="name" value="李四"/>
    <constructor-arg name="age" value="23"/>
    <constructor-arg name="gender" value="男"/>
    <constructor-arg name="banji" ref="banji"/>
</bean>

3、注解方式注入

@Resource @Autowired

六、三层架构使用Spring来管理

1、set方法注入

三层架构使用Spring来管理,达到一个目的:在上层只看到下一层的接口就可以,不需要出现具体的实现类。

使用set方式注入:

复制代码
<bean name="studentDao" class="com.situ.spring.dao.impl.StudentDaoImpl"/>
<bean name="studentService" class="com.situ.spring.service.impl.StudentServiceImpl">
    <property name="studentDao" ref="studentDao"/>
</bean>
<bean name="studentController" class="com.situ.spring.controller.StudentController">
    <property name="studentService" ref="studentService"/>
</bean>

2、注解开发方式

复制代码
<!--base-package:是要扫描的包,扫描这个包下面类上带有注解@Controller @Service @Repositioy  -->
<context:component-scan base-package="com.situ.spring"/>

@Controller @Service @Repository 本身没有区别,都是new一个对象放到Spring容器中

@Component new一个对象放到Spring容器中,不起名字,放到容器中默认的名字是类名首个单词首字母小写

复制代码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {

    /**
     * The value may indicate a suggestion for a logical component name,
     * to be turned into a Spring bean in case of an autodetected component.
     * @return the suggested component name, if any (or empty String otherwise)
     */
    @AliasFor(annotation = Component.class)
    String value() default "";

}

/*
<bean name="courseController" class="com.situ.spring.controller.CourseController">
</bean>
@Controller 这个注解相当于在applicationContext.xml中写的上面的bean,
默认的名字是类名的首个单词小写courseController
*/
@Controller("courseController")
public class CourseController {
   
   // <property name="courseService" ref="courseService"/>
   // @Resource:从Spring容器中根据名字拿出指定的对象注入进来
   @Resource(name = "courseService")
   private ICourseService courseService;
   
   public void  selectAll() {
      System.out.println("CourseController.selectAll()");
      courseService.selectAll();
   }
}

/*
<bean name="courseService" class="com.situ.spring.service.impl.CourseServiceImpl">
</bean>
*/
@Service("courseService")
public class CourseServiceImpl implements ICourseService{
   
   //<property name="courseDao" ref="courseDao"/>
   @Resource(name = "courseDao")
   private ICourseDao courseDao;
   
   @Override
   public void selectAll() {
       System.out.println("CourseServiceImpl.selectAll()");
       courseDao.selectAll();
   }
}

// <bean name="courseDao" class="com.situ.spring.dao.impl.CourseDaoImpl"></bean>
@Repository("courseDao")
public class CourseDaoIml implements ICourseDao{
   @Override
   public void selectAll() {
       System.out.println("CourseDaoIml.selectAll()");
   }
}

@Controller、@Service、@Repository这三个注解的作用和@Component是一样的,都是new一个对象放到Spring容器中,目的是为了表明三层架构中不同的层。

七、Autowired 自动装配

1、@Autowired和@Resource区别

  1. @Resource默认是按照名称装配的,是JDK提供的。
    byName 通过参数名自动装配,如果一个bean的name 和另外一个bean的 property 相同,就自动装配。
  2. @Autowired是默认按照类型装配的 ,是Spring提供的。
    byType 通过参数的数据类型自动自动装配,如果一个bean的数据类型和另外一个bean的property属性的数据类型兼容,就自动装配。

2、@Autowired一个接口有多个子类情况

复制代码
@Service
public class BanjiServiceImpl implements IBanjiService {}

@Service
public class BanjiServiceImpl2 implements IBanjiService{}


这样会报错: expected single matching bean but found 2: banjiServiceImpl,banjiServiceImpl2
因为在容器中子类对象有两个,而且变量的名字是banjiService和任何一个容器中对象的名字都不一致,所以找不到(只有一个子类对象情况下变量名可以随便写)
也同时证明,@Controller、@Service、@Repository不起名字,默认的名字是类的名字首字母变小写。
解决方法:

  1. 方法一:IBanjiService banjiServiceImpl2;
    根据变量名去容器中找相同名字的bean对象,所以注入过来的是new BanjiServiceImpl2()的对象

  2. 方法二:还是希望写成IBanjiService banjiService,@Qualifier中限定名字

    // @Resource(name = "banjiServiceImpl2")
    @Autowired
    @Qualifier(value = "banjiServiceImpl2")
    private IBanjiService banjiService;

3、@Autowired注入bean

复制代码
@Controller
public class StudentController {
  
    // <property name="studentService" ref="studentService"/>
    // @Resource(name = "studentService")
    @Autowired
    private IStudentService studentService;
    
}

//@Service("studentService")
@Service
public class StudentServiceImpl implements IStudentService{
    // @Resource(name = "studentDao")
    @Autowired
    private IStudentDao studentDao;
    
}

//@Repository("studentDao")
@Repository
public class StudentDaoImpl implements IStudentDao{
    
}
相关推荐
计算机毕设定制辅导-无忧学长6 分钟前
HTML 基础夯实:标签、属性与基本结构的学习进度(一)
前端·学习·html
希忘auto24 分钟前
Spring Cloud之负载均衡之LoadBalance
java·spring cloud
川石课堂软件测试33 分钟前
涨薪技术|Kubernetes(k8s)之Pod环境变量
java·功能测试·docker·云原生·容器·kubernetes·单元测试
ん贤34 分钟前
【数据结构】栈与队列:基础 + 竞赛高频算法实操(含代码实现)
java·数据结构·c++·算法
啾啾Fun41 分钟前
[设计模式与源码]1_Spring三级缓存中的单例模式
java·后端·spring·解耦·三级缓存·源码中的单例模式·依赖解耦
小九没绝活44 分钟前
设计模式-建造者模式
java·设计模式·建造者模式
forestsea1 小时前
Java 8 Stream API:传统实现和流式编程的范式对比
java·开发语言
小程同学>o<1 小时前
嵌入式开发之STM32学习笔记day06
笔记·stm32·学习
tan_jianhui1 小时前
用maven生成springboot多模块项目
java·spring boot·maven
多多*1 小时前
Spring设计模式 八股速记 高层模块底层模块 依赖倒置原则 开闭原则 接口隔离原则
java·开发语言·数据库·macos·github·objective-c·cocoa