初识Spring框架(详细介绍 )

目录

一、为什么学Spring?🍭

二、Sprin是什么?

  官方文档🧁

  Spring概述🍭

  特点和功能:

Ⅰ、控制反转 (IoC) 和依赖注入 (DI)

如何使用控制反转和依赖注入?

①  get、set注入方式:

②  构造注入方式

③  注解(重点)

Ⅱ、AOP  (面向切面编程)🧁

AOP相关术语

AOP的增强处理类型及特点


一、为什么学Spring?🍭

  1. 简化开发:Spring框架提供了许多功能和模块,可以大大简化企业级应用程序的开发过程。它提供了一套成熟的解决方案,涵盖了从依赖注入到面向切面编程等多个方面,使开发人员能够更专注于业务逻辑而非底层技术细节。

  2. 提高可维护性:Spring框架鼓励使用面向接口的编程方式,通过依赖注入和面向切面编程来实现松耦合的组件之间的交互。这种设计模式使代码更加模块化、可复用和易于维护。

  3. 便于集成:Spring框架具有广泛的集成能力,可以与各种第三方库、开发工具和框架无缝集成。它支持各种数据访问技术、Web框架、消息传递、安全性等,使开发人员能够灵活地选择适合自己需求的组件,同时降低了集成的复杂性。

  4. 提升测试效率:Spring框架鼓励编写可测试的代码。通过依赖注入,开发人员可以轻松地替换依赖的组件,使用Mock对象进行单元测试。此外,Spring还提供了一套测试支持类和工具,简化了集成测试和系统测试的过程。

  5. 支持企业级需求:Spring框架是为构建复杂的企业级应用程序而设计的。它提供了丰富的功能,如事务管理、安全性、缓存、调度等。这些功能使得开发人员能够轻松地处理企业级需求,并确保应用程序的可靠性和性能。

  6. 社区支持:Spring框架拥有庞大的用户社区和活跃的维护团队。这意味着您可以从其他开发人员的经验中获取帮助和支持,找到解决问题的最佳实践,并及时获得更新和修复bug的版本。

二、Sprin是什么?

  官方文档🧁

Spring | Why Springhttps://spring.io/why-spring

  Spring概述🍭

       Spring框架是一个用于构建企业级Java应用程序的开源框架。它提供了一套全面的解决方案,使开发人员能够更轻松地创建可维护、灵活和可扩展的应用程序。

  特点和功能:

  1. 轻量级:Spring框架采用了基于POJO(Plain Old Java Object)的开发模式,避免了对特定的容器或框架的依赖,从而使应用程序更加轻量级。

  2. 依赖注入(Dependency Injection):通过依赖注入,Spring框架能够管理对象之间的依赖关系。这种方式可以降低组件之间的耦合度,并使测试变得更加容易。

  3. 面向切面编程(Aspect-Oriented Programming):Spring支持面向切面编程,使开发人员能够将与业务逻辑无关的功能(例如日志记录、安全性、事务管理等)从应用程序主体中分离出来。

  4. 容器:Spring框架提供了一个容器(ApplicationContext),该容器负责创建和管理应用程序中的对象。它还支持各种配置选项,如XML配置、Java注解和基于Java的配置。

  5. 数据访问:Spring提供了对各种数据访问技术的集成支持,包括JDBC、ORM框架(如Hibernate和MyBatis)以及NoSQL数据库。

  6. Web开发:Spring框架还提供了用于构建Web应用程序的模块,如Spring MVC。它简化了开发过程,并提供了灵活的配置选项。

  7. 测试:Spring框架鼓励编写可测试的代码,它提供了一套测试支持类和工具,如Mock对象、测试注解和集成测试支持。

注:Spring的核心是IoC(控制反转)和AOP(面向切面编程)!!!

Ⅰ、控制反转 (IoC) 和依赖注入 (DI)

         在之前,开发人员需要通过new来创建对象的生命周期,每new一次对象就会重新开辟一个空间。导致代码与对象的创建和依赖关系紧密耦合,难以维护和拓展,还很浪费内存

package domain;

import org.junit.Test;

public class UserTest {

    @Test
    public void TestDemo(){
        //创建第一个对象
        User user=new User(); 
        user.setId(1);
        user.setName("张三");
        //创建第二个对象
        User user1=new User();
        user1.setName("李四");
        //判断这两个对象是否是同一个对象
        System.out.println(user1==user);
        //输出
        System.out.println(user.toString());
        System.out.println(user1.toString());
    }
}

              使用我们的控制反转 (IoC) 和依赖注入 (DI) 就能很好的解决这个问题!

控制反转IoC,Inversion of Control)将创建对象交给Spring框架负责,而不是开发人员手动管理。

依赖注入DI,Dependency Injection):是控制反转的一种实现方式,通过将对象的依赖关系注入到对象中,使对象能够获取所需的依赖,而无需自己创建和管理依赖对象。依赖注入通过配置文件或注解的方式,将对象之间的依赖关系描述清楚,并由框架负责解析和注入。

如何使用控制反转和依赖注入?

      可以通过三种方式实现依赖注入:① get、set 注入 ② 构造方法注入 ③ p命名空间注入 ④注解注入

1、先导入jar包 (用的Maven项目)

 <dependency>
           <groupId>org.projectlombok</groupId>
           <artifactId>lombok</artifactId>
           <version>1.18.24</version>
       </dependency>
       <!-- 1.Spring核心依赖 -->
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-core</artifactId>
           <version>4.3.7.RELEASE</version>
       </dependency>
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-beans</artifactId>
           <version>4.3.7.RELEASE</version>
       </dependency>
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-context</artifactId>
           <version>4.3.7.RELEASE</version>
       </dependency>
       <!-- 2.Spring dao依赖-->
       <!-- spring-jdbc包括了一些如jdbcTemplate的工具类-->
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-jdbc</artifactId>
           <version>4.3.7.RELEASE</version>
       </dependency>

       <!-- 3.Spring web依赖 -->

       <!-- 4.Spring test依赖:方便做单元测试和集成测试 -->
       <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-test</artifactId>
       <version>4.3.7.RELEASE</version>
       </dependency>
       <dependency>
           <groupId>junit</groupId>
           <artifactId>junit</artifactId>
           <version>4.13.2</version>
           <scope>test</scope>
       </dependency>

①  get、set注入方式:
  • 一般用于对象,编写实体类
package com.cskt.domain;

import lombok.Data;

/**
 * domain————实体类
 */
@Data
public class User {
    private int id;
    private String name;
    private String content;

    public void print(){
        System.out.println(name+":“"+content+"“");
    }
}
  • 配置文件  编写 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"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

<!--  通过id属性为该实例指定一个名称,class放的是全路径(反射模式) -->
    <bean id="user" class="com.cskt.domain.User">
        <property name="name" value="张三"></property>
        <property name="id" value="2"></property>
    </bean>
</beans>
  • 测试
package domain;

import com.cskt.domain.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UserTest {

    @Test
    public void Test(){
        ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
        User user =(User) context.getBean("user");
        System.out.println(user);
    }
}
②  构造注入方式
  • 构造注入的方式一般用于 dao 层和service 层的
package com.cskt.service.impl;

import com.cskt.domain.User;
import com.cskt.mapper.UserMapper;
import com.cskt.service.UserService;

public class UserServiceImpl implements UserService {
    
    //实例化所依赖的UserMapper对象
    //重复的new对象  构造注入  就是解决Service 和 dao 的问题
    private UserMapper userMapper;  

    //添加构造函数
    public UserServiceImpl(UserMapper userMapper) {
        this.userMapper = userMapper;
    }

    @Override
    public int insert(User sysUser) {
        int count = userMapper.insert(sysUser);
        return count;
    }
}
  • class属性放的是daoImpl的全路径,不是dao层 
<!-- 构造注入 1、先把dooImpl 注入进来  2、在service 写一个构造函数依赖注入 -->
<bean id="userMapper" class="com.cskt.mapper.impl.UserMapperImpl"></bean>
<bean id="userService" class="com.cskt.service.impl.UserServiceImpl">
    <constructor-arg ref="userMapper"></constructor-arg>
</bean>
  • 测试类只需要把之前new  serviceImpl() 换成 context.getBean(""),从IoC容器拿
@Test
public void insert() {
    ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
    UserService userService =(UserService) context.getBean("userService");
    userService.insert(new User());
}

③  注解(重点)

        注:  注解是我们项目中常用的,所以我们重点记住注解。但是前面哪几种还是要了解的!!!

  • @Component:实现Bean组件的定义

  • @Repository:用于标注DAO类

  • @Service:用于标注业务类

  • @Controller:用于标注控制器类

( 他是通过这四个注解来实现的 )

  • 因为需要操作的类,只有MapperImpl和serviceImpl实现类。所以我们只需要修改dao和service的实现类就可以了。给他们加上相应的注解。
package com.cskt.mapper.impl;

import com.cskt.domain.User;
import com.cskt.mapper.UserMapper;
import org.springframework.stereotype.Repository;

@Repository //等效于  <bean id="userMapper" class="com.cskt.mapper.impl.UserMapperImpl" />
            //如果变量名规范的话就可以不用加括号  ("userMapper") 
public class UserMapperImpl implements UserMapper {
    @Override
    public int insert(User sysUser) {
        //这里未实现完整的数据库操作,仅为说明原因
        System.out.println("执行了新增的方法。。。。");
        return 0;
    }
}
package com.cskt.service.impl;

import com.cskt.domain.User;
import com.cskt.mapper.UserMapper;
import com.cskt.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

@Service("userService")   /*等效于  <bean id="userService" class="com.cskt.service.impl.UserServiceImpl">
                                        <constructor-arg ref="userMapper"></constructor-arg>
                                   </bean> */
public class UserServiceImpl implements UserService {

    //实例化所依赖的SysUserMapper对象
    //重复的new对象  构造注入  就是解决Service 和 dao 的问题

    @Autowired //自动装配  只要命名规范 就会自动装配
    //@Qualifier("userMapper")  //如果获取不到,  如果指定装配哪一个
    private UserMapper userMapper;

    @Override
    public int insert(User sysUser) {
        int count = userMapper.insert(sysUser);
        return count;
    }
}
  • 给MapperImpl和serviceImpl添加好了注解。一定一定要记得添加扫描,不然会注入不进入。开启就代表着自动帮你识别放入包中的所有注解。没开启扫描的话,那我们的注解是没有用的!!!!
  <!-- 扫描包中注解标注的类,如果不加的话会导致注入不进去 -->
<context:component-scan base-package="com.cskt.mapper,com.cskt.service" />

   测试类就跟构造注入的测试类一样,并不需要改。

Ⅱ、AOP  (面向切面编程)🧁

   AOP全称Aspect Oriented Programming,也叫面向切面编程。AOP是在方法中找到共同的代码提取出来,编成一个切面。通过动态代理的方式,把抽离出来的共性代码 “织入”到业务中。

AOP相关术语
  • Aspect(切面)
  • Advice(增强处理)
  • Pointcut(切入点)
  • Join Point(连接点)
  • Target Object(目标对象)
  • AOP proxy(AOP 代理)
  • Weaving(织入)

AOP的增强处理类型及特点

( 这里也是通过注解的方式 )

  1.  前置增强:前置增强是在目标方法执行之前执行的增强。它可以用于在目标方法执行前进行一些预处理操作,例如验证输入参数、记录日志或者进行安全性检查。前置增强没有能力改变目标方法的执行结果。
    /**
    * 前置通知
    */
    @Before("execution(* com.cskt.service..*.*(..)))")
    public void before(){
    	System.out.println("前置通知.... 在方法之前要執行的公共代码放在这里");
    }

  2.  后置增强:后置增强是在目标方法执行之后执行的增强。它可以用于在目标方法执行完毕后进行一些操作,例如记录日志、清理资源或者转换返回值等。后置增强不能修改目标方法的执行结果。
    /**
    * 后置通知
    * returnVal,切点方法执行后的返回值
    */
    @AfterReturning(value="execution(* com.cskt.service..*.*(..)))",returning = "returnVal")
    public void AfterReturning(Object returnVal){
    	System.out.println("后置通知...."+returnVal);
    }

  3.  异常抛出增强:异常增强是在目标方法抛出异常后执行的增强。它可以用于捕获目标方法抛出的特定异常并采取相应的处理措施,例如记录日志、发送警报或者进行回滚操作。
    /**
    * 抛出通知
    * @param e
    */
    @AfterThrowing(value="execution(* com.cskt.service..*.*(..))",throwing = "e")
    public void afterThrowable(Throwable e){
    	System.out.println("出现异常:msg="+e.getMessage());
    }

  4.  最终增强:最终增强是在目标方法执行之后(无论是否抛出异常)都会执行。最终增强通常用于释放资源、清理操作或者进行一些必要的收尾工作。
    /**
    * 无论什么情况下都会执行的方法
    */
    @After(value="execution(* com.cskt.service..*.*(..))")
    	public void after(){
    	//方法的对象的关闭
    	//方法的回滚
    	System.out.println("最终通知....");
    }

  5.  环绕增强:环绕增强是最强大和最灵活的增强类型。它可以在目标方法执行前后都执行自定义逻辑,并且可以完全控制目标方法的调用。环绕增强可以决定是否调用目标方法、如何处理输入参数、错误处理等。它还可以修改目标方法的返回值。
/**
* 环绕通知
* @param joinPoint 可用于执行切点的类
*                  具体什么业务
* @return
* @throws Throwable
*/
@Around("execution(* com.cskt.service..*.*(..))")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
	System.out.println("环绕通知前....");
	Object obj= (Object) joinPoint.proceed();
	System.out.println("环绕通知后....");
	return obj;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值