SSM框架学习笔记


一、Spring

Spring是一个分层的Java SE/EE应用一站式的轻量级开源框架。Spring核心是IOC(Inversion of Control)AOP(Aspect Oriented Programming)

Spring主要优点包括:

  • 方便解耦,简化开发,通过Spring提供的IoC容器,我们可以将对象之间的依赖关系交由Spring进行控制,避免硬编码造成的程序耦合度高。
  • AOP编程的支持,通过Spring提供的AOP功能,方便进行面向切面编程。
  • 声明式事务的支持,在Spring中,我们可以从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。
  • 方便程序的测试,可以用非容器依赖的编程方式进行几乎所有的测试工作。
  • 方便集成各种优秀框架,Spring提供了对各种优秀框架的直接支持。

Spring框架结构组成图如下所示:
在这里插入图片描述


0、 配置

  1. pom.xml添加spring依赖
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.10.RELEASE</version>
</dependency>
  1. 在resources文件夹内新建applicationContext.xml文件
//在beans标签内,新建bean标签
<!--配置bean-->
<!--bean标签表示配置bean-->
<!--id属性为bean的标识名称-->
<!--name属性给bean起名-->
<!--class属性表示给bean定义类型-->
<bean id="bookDao" name="bookDao2,dao" class="com.minqo.dao.impl.BookDaoImpl"></bean>
  1. 管理bean
    程序主要是通过Spring容器来访问容器中的Bean,ApplicationContext是Spring容器最常用的接口,该接口有如下两个实现类:
  • ClassPathXmlApplicationContext: 从类加载路径下搜索配置文件,并根据配置文件来创建Spring容器。
  • FileSystemXmlApplicationContext: 从文件系统的相对路径或绝对路径下去搜索配置文件,并根据配置文件来创建Spring容器
//获取Ioc容器
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

//获取bean
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
BookDao bookDao = ctx.getBean("bookDao",BookDao.class); 
BookDao bookDao = ctx.getBean(BookDao.class); //按类查找,这种方法中,beans中只能有一个BookDao

1、Ioc

Inversion of Control控制反转:将对象的创造控制权移交到Core Container容器,降低类与类之间的耦合性。
BeanFactory为Ioc容器顶层接口,初始化BeanFactory对象时,加载的bean延迟加载
Application为Spring容器的核心接口,初始化时bean立即加载

调用方法时,从Ioc容器中通过id获取bean,根据bean中的关系来关联其他类
若没有property关系,则当前类中的其他类为Null。当前类中的set方法由Ioc容器调用
示例代码如下:

public class BookDaoImpl implements BookDao {
    public void save(){
        System.out.println("book dao save ...");
    }
}
public class BookServiceImpl implements BookService {
    private BookDao bookDao;

    public void save(){
        System.out.println("book sesrvice save ...");
        bookDao.save();
    }
    //Ioc容器调用
    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }
}
public class App2 {
    public static void main(String[] args) {
        //获取Ioc容器
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

        //获取bean
        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
        bookDao.save();

        BookService bookService = (BookService) ctx.getBean("bookService");
        bookService.save();
    }
}
<bean id="bookDao" class="com.minqo.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="com.minqo.service.impl.BookServiceImpl">
       <!--配置关系-->
        <!--
        property标签表示当前bean的属性
        name属性表示配置哪个具体属性 //类的属性
        ref属性表示参照哪个bean	//bean的id
        -->
        <property name="bookDao" ref="bookDao"/>
</bean>

Bean

生命周期:

  • 初始化容器
    1. 创建对象(内存分配)
    1. 执行构造方法
    1. 执行属性注入(set操作)
    1. 执行bean初始化方法
  • 使用bean
    1. 执行业务操作
  • 关闭/销毁容器
    1. 执行bean销毁方法
  1. name属性可以用来取别名,名字间可用, ; (空格)相隔,ref属性也可以通过其他bean的name属性获取其他bean
  2. scope属性可以设置bean为单例singleton(默认)/非单例prototype,即获取bean为同一个对象或多个对象
  3. 含有成员属性值的不适合作为bean交给容器
  4. init-method || destroy-method属性设置bean初始化||结束的方法,在daoImpl建立init()与destroy()方法赋值给属性值。
  • 调用容器的close()方法,会调用destroy方法强制关闭容器。
  • 在容器创建后任何地方调用容器的registerShutdownHook()方法,在虚拟机运行结束前会将容器关闭。
  1. lazy-init属性控制bean的延迟加载(获取bean时是否调用构造方法)

依赖注入

bean之间的相互依赖关系,通过注入的方式使数据在bean与bean之间传输

  • setter注入(通过set方法)
    1. 简单类型:在bean中定义引用数据类型属性,并定义其set方法,在配置文件中使用property标签中的value属性注入简单数据类型,name属性值为属性名
    1. 引用类型:在bean中定义引用数据类型属性,并定义其set方法,在配置文件中使用property标签中的ref属性,找到引用数据的bean的id,name属性值为属性名
private int num;
private String name;
public void setNum(int num) {
        this.num = num;
}
public void setName(String name) {
        this.name = name;
}    
<bean id="bookDao" class="com.minqo.dao.impl.BookDaoImpl" >
        <property name="num" value="10"/>
        <property name="name" value="name"/>
</bean>
private BookDao bookDao;
public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
}
<bean id="bookService" class="com.minqo.service.impl.BookServiceImpl" >
        <property ref="bookDao" name="bookDao"/>
</bean>
  • 构造器注入(通过构造方法)
    1. 简单类型:在bean中定义引用数据类型属性,在构造方法中通过参数实例化属性,在配置文件中使用constructor-arg标签中的value属性注入简单数据类型,name属性值为构造方法中的参数名
    1. 引用类型:在bean中定义引用数据类型属性,在构造方法中通过参数实例化属性,在配置文件中使用constructor-arg标签中的ref属性,找到引用数据的bean的id,name属性值为构造方法中的参数名
  • 构造器注入中,注入需要联系构造方法中的参数名可以通过index属性,通过参数的位置注入,耦合度过高,使用setter更好
private int num;
private String name;
public BookDaoImpl(int num, String name) {
        this.num = num;
        this.name = name;
}
<bean id="bookDao" class="com.minqo.dao.impl.BookDaoImpl" >
        <constructor-arg index="1" value="name"/>
        <constructor-arg index="0" value="10"/>
</bean>
public BookServiceImpl(BookDao bookDao) {
        this.bookDao = bookDao;
}
<bean id="bookService" class="com.minqo.service.impl.BookServiceImpl" >
        <constructor-arg ref="bookDao" name="bookDao"/>
</bean>

自动装配

通过bean标签的autowire属性,设置自动装配的类型自动装配用于引用类型依赖注入,不能对简单类型操作

  • byType,通过类型匹配,一个属性变量只能有一个bean标签即相同bean标签唯一
  • byName,通过名字匹配,即bean的id与set xxx的xxx匹配,耦合度较高
private BookDao bookDao;
<bean id="bookDao" class="com.minqo.dao.impl.BookDaoImpl" >
<bean id="bookService" class="com.minqo.service.impl.BookServiceImpl"  autowire="byType">

集合注入

书写格式如下(setter注入):

private int[] array;
private List list;
private Map map;

<property name="array">
     <array>
         <value>10</value>
         <value>102</value>
         <value>103</value>
     </array>
</property>

<property name="list">
     <list>
         <value>10</value>
         <value>102</value>
     </list>
</property>

<property name="map">
     <map>
         <entry key="10" value="min"></entry>
     </map>
</property>

加载properties文件

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       //在xml新开辟命名空间:context
       xmlns:context="http://www.springframework.org/schema/context"
       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">

	//context属性占位符,location表示文件位置,多个文件用逗号隔开,classpath表示类路径,
	//classpath*包含jar包中的文件,*.properties表示引用全部文件,system-properties-mode为系统变量,当文件变量名与系统变量(优先级高)名相同时,通过设置属性值“NEVER”来限制系统变量属性值。
    <context:property-placeholder location="test.properties"/>
    <context:property-placeholder location="classpath*:*.properties" system-properties-mode="NEVER"/>


<bean id="bookDao" class="com.minqo.dao.impl.BookDaoImpl" >
        <constructor-arg value="${test}"/>   //利用${}占位符读取文件中的数据
</bean>

2、注解开发

在类的上方用注解标注来标识该类将作为Ioc容器中的bean
在xml文件中删除对应的bean

@Component("bookDao")  //声明bean并设置id
public class BookDaoImpl implements BookDao 

@Component     //不设置id可以通过按类查找
public class BookServiceImpl implements BookService

//在xml中扫描component注解
<context:component-scan base-package="com.minqo"/>


BookDao bookDao = (BookDao) ctx.getBean("bookDao");
bookDao.save();
BookService bookService = ctx.getBean(BookService.class);
bookService.save();

@Component注解的衍生注解

  • @Controller:用于表现层bean的定义
  • @Service:用于业务层bean的定义
  • @Repository:用于数据层bean的定义

纯注解开发

Spring3.0开启纯注解开发,使用java类代替配置文件

//新建java类,@Configuration注解定义当前类为配置类
//@ComponentScan注解用于设定扫描路径,若有多个数据,用字符串数组格式表示
@Configuration
@ComponentScan("com.minqo")
public class SpringConfig {
}
//加载配置文件初始化容器->加载配置类初始化容器
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);


@Scope("singleton" / "prototype") //@Scope注解设置单多例

@PostConstruct  //生命周期,方法名自拟
public void init(){
     System.out.println("init...");
}
@PreDestroy
public void destroy(){
      System.out.println("desrtoy..");
}

依赖注入

使用@Autowired注解开启自动装配(按类型)
自动装配基于反射设计创建对象并暴力反射对应属性私有属性初始化数据,无需提供setter方法
自动装配建议使用无参构造方法创建对象(默认)
使用@Qualifier注解开启指定名称装配bean(当一个类含有多个其他类)

@Autowired
@Qualifier("bookDao")
private BookDao bookDao;

@Autowired
@Qualifier("bookDao2")
private BookDao bookDao;

@Repository("bookDao")
public class BookDaoImpl implements BookDao 

@Repository("bookDao2")
public class BookDaoImpl2 implements BookDao 

使用@Value注解对基本数据类型进行赋值,从配置文件中读取数据,耦合度低。

@Configuration
@ComponentScan("com.minqo")
@PropertySource("test.properties")
public class SpringConfig {
}

@Value("minqo")
String name;
@Value("${test}")
String name2;

第三方bean的依赖注入

通过将@Bean注释添加到自拟方法上,方法的返回值作为Bean。
通过@Import注释导入含有第三方Bean的类。
引用类型依赖注入,只需要为Bean定义形参即可,容器会根据类型自动装配对象
简单类型依赖注入,通过@Value注释赋值。

@Configuration
@ComponentScan("com.minqo")
@PropertySource("test.properties")
@Import(JdbcConfig.class)
public class SpringConfig {
}

public class JdbcConfig {
    @Value("minqo")
    String name;

    @Bean
    public DataSource dataSource(BookDao bookDao){
        DruidDataSource ds = new DruidDataSource();
        ds.setName(name);
        System.out.println(ds);
        bookDao.save();
        return ds;
    }
}

3、AOP

0.简介

OOP(Object Orient Programming)面向对象编程
AOP(Aspect OrientProgramming)面向切面编程,AOP专门用于处理系统中分布于各个模块(不同方法)中的交叉关注点的问题,在JavaEE应用中,常常通过AOP来处理一些具有横切性质的系统级服务,如事务管理、安全检查、缓存、对象池管理等,AOP已经成为一种非常常用的解决方案。

作用:在不改变原始设计的基础上进行功能增强

面向编程:

  • 连接点(Joinpoint): 程序执行过程中明确的点,如方法的调用,或者异常的抛出。在Spring AOP中,连接点总是方法的调用。
  • 切入点(Pointcut): 匹配连接点的式子,可以插入增强处理的连接点。简而言之,当某个连接点满足指定要求时,该连接点将被添加增强处理,该连接点也就变成了切入点。在SpringAOP中,一个切入点可以只描述一个方法,也可以匹配多个方法。
  • 通知(Advice): AOP框架在特定的切入点执行的增强处理。处理有“around”、“before”、“after”等类型。共性功能。
  • 切面(Aspect): 切面用于组织多个Advice,Advice放在切面中定义。

1.配置

  1. pom.xml导入依赖
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.10.RELEASE</version>
</dependency>
<dependency>
	 <groupId>org.aspectj</groupId>
	 <artifactId>aspectjweaver</artifactId>
	 <version>1.9.4</version>
</dependency>
  1. 新建通知类
    @Component注解标识该类作为bean,用@Aspect标识该类作为AOP处理,作为切面类
    @Pointcut注解标识方法作为切入点增强处理,参数为匹配的方法,该注解放在无返回值、无参数的类上,方法体无具体实意
    @Before注解标识方法作为增强处理内容,在参数方法执行前执行增强的内容。绑定切入点与通知的关系
    @EnableAspectJAutoProxt注释标识该Spring框架开启AOP注解驱动
@Component
@Aspect
public class MyAdvice {
    @Pointcut("execution(void com.minqo.dao.Impl.BookDaoImpl.update())")
    public void fd(){

    }

    @Before("fd()")
    public void method(){
        System.out.println(System.currentTimeMillis());
    }
}
@Configuration
@ComponentScan("com.minqo")
@EnableAspectJAutoProxy
public class SpringConfig {
}

2.流程

  1. 启动Spring容器
  2. 获取切面中所有切入点
  3. 获取bean,判断bean中是否有方法与切入点匹配
    • 匹配失败,创建bean
    • 匹配成功,创建原始对象(目标对象)的代理对象
  4. 获取bean的执行方法
    • 获取bean,调用方法并执行,完成操作
    • 获取的是bean的代理对象时,根据代理对象运行操作以及增强操作

目标对象(Target):原始功能去掉共性功能(增强处理,上方的method())对应的类产生的对象,无法直接完成最终操作
代理(Proxy):原始对象无法直接完成最终任务,通过对其进行增强处理,将其原始对象扩展为代理对象

3.AOP切入点表达式

切入点表达式格式:动作关键词(访问修饰符 返回类型 包.类.方法(参数) 异常抛出)

  • 动作关键词:描述切入点的动作,例如execution描述执行到制定切入点
  • 访问修饰符:public、private等,可以省略
  • 异常抛出:方法定义中抛出的指定方法,可省略

可以使用通配符描述切入点,快速描述

  • *:单个独立的任意符号,可以独立出现,也可以作为前缀或者后缀的匹配符出现
    execution (public * com.minqo.*.UserService.find* (*))
    匹配com.minqo包下的任意包中的UserService类或接口中所有find开头的带有一个参数的方法
  • . . : 多个连续的任意符号,可以独立出现,常用于简化包名与参数的书写
    execution (public User com. .UserService.findById(. .))
    匹配com包下的任意包中的UserService类或接口中所有名称为findByld的方法
  • +:专用于匹配子类类型
    execution(* *. .Service+.(. .))

4.通知(Advice)类型

@Pointcut("execution(int com.minqo.dao.Impl.BookDaoImpl.select(..))")
public void fd2(){
}

public int select(){
   System.out.println("select ...");
   return 100;
}
  • 前置通知:@Before注解,设置当前方法(before())切入点(fd2())间的绑定关系,当前通知方法在切入点之前执行
 @Before("fd2()")
 public void before(){
     System.out.println("before advice.");
 }
  • 后置通知:@After注解,设置当前方法(after())切入点(fd2())间的绑定关系,当前通知方法在切入点之后执行
@After("fd2()")
public void after(){
    System.out.println("after advice..");
}
  • 环绕通知:@Around注解,设置当前方法(around())切入点(fd2())间的绑定关系,当前通知方法可以在切入点前后执行。原始方法中的内容必须通过形参ProceedingJoinPoint 执行,若没有该形参,原始方法中的操作将被覆盖。接收返回值,代理方法需要将返回类型设置为Object。因为无法预测原始方法是否出错,需要抛出异常
@Around("fd2()")
public Object around(ProceedingJoinPoint pjt) throws Throwable {  //抛出异常,防止原始方法还有异常AOP切面无法处理
    System.out.println("around before.");
    Object obj = pjt.proceed(); //执行原始方法中的操作(以上作为切入点的方法还有返回值)
    System.out.println("around after.");
    return obj;
}
  • 返回后通知:@AfterReturning注解,设置当前方法(afterReturn())切入点(fd2())间的绑定关系,当前通知方法在切入点返回之后执行,若切入点未返回不执行该操作
@AfterReturning("fd2()")
public void afterReturn(){
    System.out.println("afterReturning.");
}
  • 执行异常后通知:@AfterThrowing注解,设置当前方法(afterThrow())切入点(fd2())间的绑定关系,当前通知方法在切入点抛出异常之后执行,若切入点未抛出异常不执行该操作
@AfterThrowing("fd2()")
public void afterThrow(){
    System.out.println("afterThrow");
}

5.AOP通知获取数据

  1. 获取参数
    • JoinPoint:适用于前置、后置、返回后、抛出异常通知

    • ProceedJointPoint:适用于环绕通知

@Before("fd2()")
public void before(JoinPoint jp){
    Object[] args = jp.getArgs();
    System.out.println(Arrays.toString(args));
    System.out.println("before advice.");
}

@Around("fd2()")
public Object around(ProceedingJoinPoint pjt) throws Throwable {  //抛出异常,防止原始方法还有异常AOP切面无法处理
    System.out.println("around before.");
    Object[] args = pjt.getArgs();
    args[0] = 50;  	//可以修改原参数
    pjt.proceed(args); //执行原始方法中的操作(以上作为切入点的方法还有返回值)
    System.out.println("around after.");
    return 200;
}
  1. 获取返回值
    • 返回后通知
    • 环绕通知
@AfterReturning(value = "fd2()",returning = "ret")//参数returning的值与Object参数名称对应
public void afterReturn(JoinPoint jp,Object ret){
   System.out.println("afterReturning."+ret);
}
  1. 获取异常
    • 抛出异常后通知
    • 环绕通知
@AfterThrowing(value = "fd2()",throwing = "t")//参数名称对应
public void afterThrow(Throwable t ){
  System.out.println("afterThrow");
}

@Around("fd2()")
public Object around(ProceedingJoinPoint pjt){
    System.out.println("around before.");
    try {
        pjt.proceed();
    } catch (Throwable e) { //捕捉异常
        System.out.println(e);
        throw new RuntimeException(e);
    }
    System.out.println("around after.");
    return 200;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java SSMSpring+SpringMVC+MyBatis)是一种基于Java语言的Web开发框架学习这个框架的过程中,我深刻体会到它的强大和灵活性。 首先,Spring框架为开发者提供了一个强大的IOC(Inversion of Control)容器,它能够管理和注入对象,减少了代码之间的耦合性。通过配置文件或注解,我们可以轻松地定义和获取各种对象,提高了代码的可维护性和可扩展性。 其次,SpringMVC框架是一种MVC(Model-View-Controller)设计模式的实现,它用于处理Web请求和响应。通过配置一个请求映射表和处理器,我们可以将请求分发给相应的控制器进行处理,并将处理结果返回给客户端。SpringMVC还提供了一些便捷的注解和标签,用于简化页面的渲染和参数的绑定。 最后,MyBatis是一种优秀的持久化框架,它能够将数据库操作与Java对象之间的映射简化为简单的配置。通过编写SQL映射文件和定义POJO(Plain Old Java Object)类,我们可以方便地进行数据库的增删改查操作,而无需编写冗长的SQL语句。 在学习Java SSM框架的过程中,我深入理解了软件开发过程中的MVC思想,并学会了如何利用SpringSpringMVC和MyBatis来实现一个完整的Web应用程序。通过不断的实践和调试,我逐渐培养了自己解决问题和调试代码的能力。 总结起来,学习Java SSM框架使我深入理解了软件开发的各个环节,并提升了我的编码能力和开发效率。我相信这些知识和经验将对我的职业发展和项目实施起到积极的促进作用。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值