Spring常用注解,注解 IOC ,AOP,MVC 的理解

Spring常用注解,注解 IOC ,AOP,MVC 的理解,第1张

Spring常用注解,注解 IOC ,AOP,MVC 的理解

文章目录
  • 大佬总结
  • 0、Spring常用注解
    • 0.1、SpringBootController里面的用法
      • 0.1.1、SpringBoot 中常用注解@Controller/@RestController/@RequestMapping/@SpringBootApplication介绍
      • 0.1.2、@SpringBootApplication
      • 0.1.3、@RequestMapping与@GetMapping和@PostMapping等新注释
      • 0.1.4、@PathVariable注解使用
      • 0.1.5、@RequestParam注解使用
    • 0.2、Spring Boot 自定义配置
      • 0.2.1spring的@Value注解和@ConfigurationProperties注解使用
      • 0.2.2 Spring注解@Component、@Repository、@Service、@Controller区别
        • 0.2.2.2@Repository的作用?
        • 0.2.2.3 @component
        • 0.2.2.4 @Autowired用法
        • 0.2.2.5 对@Reference 、@Resource和@Autowired的简单理解
        • @Slf4j
    • 0.3、 spring注解@Service注解的使用
  • 1、IOC
    • 1.1、IOC简介
    • 为什么叫控制反转
    • 1.2、 IOC的主要实现方式
      • 依赖注入
    • 1.2.1、 IoC容器
    • 1.2.2 、依赖注入
      • 1.2.2.1、基于注解注入方式
      • @Autowired与@Resource区别
      • 1.2.2.2、属性setter注入
      • 1.2.2.3、静态工厂方式实例化
      • 1.2.2.4、实例工厂实例化
    • IoC 解决了什么问题
    • **面试怎么回答:**
  • 2、 AOP
    • 2.1、AOP简单理解
    • 2.2、 AOP涉及名词
    • AOP 解决了什么问题
    • AOP 为什么叫面向切面编程
    • Spring AOP 和 AspectJ AOP 有什么区别?
  • 3、SpringMVC:
    • Spring框架用了那些设计模式?
    • DAO层,Service层,Controller层、View层

大佬总结

(面试必备)超详细Spring IOC、AOP、事务解析及其案例

0、Spring常用注解
  1. Spring常用注解

在具体介绍IOC和AOP之前,我们先简要说明下Spring常用注解

0.1、SpringBootController里面的用法 0.1.1、SpringBoot 中常用注解@Controller/@RestController/@RequestMapping/@SpringBootApplication介绍

@Controller/@RestController/@RequestMapping介绍

0.1.2、@SpringBootApplication

声明这是一个Springboot的应用

0.1.3、@RequestMapping与@GetMapping和@PostMapping等新注释

@RequestMapping与@GetMapping和@PostMapping

0.1.4、@PathVariable注解使用

@PathVariable注解使用

0.1.5、@RequestParam注解使用

@RequestParam注解使用

0.2、Spring Boot 自定义配置

在 SpringBoot 的核心配置文件中,除了使用内置的配置项之外,我们还可以在自定义配
置,然后采用如下注解去读取配置的属性值

0.2.1spring的@Value注解和@ConfigurationProperties注解使用

spring的@Value注解使用

@ConfigurationProperties

0.2.2 Spring注解@Component、@Repository、@Service、@Controller区别

Spring注解@Component、@Repository、@Service、@Controller区别

0.2.2.2@Repository的作用?

@Repository的作用?

@Repository的作用

0.2.2.3 @component

@component
@component

0.2.2.4 @Autowired用法

@Autowired 的作用是什么?

0.2.2.5 对@Reference 、@Resource和@Autowired的简单理解

对@Reference 、@Resource和@Autowired的简单理解

@Slf4j

@Slf4j

0.3、 spring注解@Service注解的使用

spring注解@Service注解的使用

1、@Controller:用于标注控制器层组件

2、@Service:用于标注业务层组件

3、@Component : 用于标注这是一个受 Spring 管理的组件,组件引用名称是类名,第一个字母小写。可以使用@Component(“beanID”) 指定组件的名称

4、@Repository:用于标注数据访问组件,即DAO组件

5、@Bean:方法级别的注解,主要用在@Configuration和@Component注解的类里,@Bean注解的方法会产生一个Bean对象,该对象由Spring管理并放到IoC容器中。引用名称是方法名,也可以用@Bean(name = “beanID”)指定组件名

6、@Scope(“prototype”):将组件的范围设置为原型的(即多例)。保证每一个请求有一个单独的action来处理,避免action的线程问题。

由于Spring默认是单例的,只会创建一个action对象,每次访问都是同一个对象,容易产生并发问题,数据不安全。

7、@Autowired:默认按类型进行自动装配。在容器查找匹配的Bean,当有且仅有一个匹配的Bean时,Spring将其注入@Autowired标注的变量中。

8、@Resource:默认按名称进行自动装配,当找不到与名称匹配的Bean时会按类型装配。

简单点说,就是,能够明确该类是一个控制器类组件的,就用@Controller;能够明确是一个服务类组件的,就用@Service;能够明确该类是一个数据访问组件的,就用@Repository;不知道他是啥或者不好区分他是啥,但是就是想让他动态装配的就用@Component。

@Controller、@Service、@Component、@Repository都是类级别的注解,如果一个方法也想动态装配,就用@Bean。

当我们想按类型进行自动装配时,就用@Autowired;当我们想按名称(beanID)进行自动装配时,就用@Resource;当我们需要根据比如配置信息等来动态装配不同的组件时,可以用getBean(“beanID”)。

到这里,如果对这些注解,或是自动装配不太理解,可以继续往下,看完 控制反转(IoC) 内容后再回来理解这里的内容。

1、IOC 1.1、IOC简介

IOC(Inverse of Control):控制反转,也可以称为依赖倒置。

所谓依赖,从程序的角度看,就是比如A要调用B的方法,那么A就依赖于B,反正A要用到B,则A依赖于B。所谓倒置,你必须理解如果不倒置,会怎么着,因为A必须要有B,才可以调用B,如果不倒置,意思就是A主动获取B的实例:B b = new B(),这就是最简单的获取B实例的方法(当然还有各种设计模式可以帮助你去获得B的实例,比如工厂、Locator等等),然后你就可以调用b对象了。所以,不倒置,意味着A要主动获取B,才能使用B;到了这里,就应该明白了倒置的意思了。倒置就是A要调用B的话,A并不需要主动获取B,而是由其它人自动将B送上门来。

IoC (Inversion of control )控制反转/反转控制。它是一种思想不是一个技术实现。描述的是:Java 开发领域对象的创建以及管理的问题。

例如:现有类 A 依赖于类 B

传统的开发方式 :往往是在类 A 中手动通过 new 关键字来 new 一个 B 的对象出来
使用 IoC 思想的开发方式 :不通过 new 关键字来创建对象,
而是通过 IoC 容器(Spring 框架) 来帮助我们实例化对象。我们需要哪个对象,直接从 IoC 容器里面过去即可。

从以上两种开发方式的对比来看:我们 “丧失了一个权力” (创建、管理对象的权力),从而也得到了一个好处(不用再考虑对象的创建、管理等一系列的事情)

为什么叫控制反转

控制 :指的是对象创建(实例化、管理)的权力

反转 :控制权交给外部环境(Spring 框架、IoC 容器)

控制反转,简单点说,就是创建对象的控制权,被反转到了Spring框架上。

通常,我们实例化一个对象时,都是使用类的构造方法来new一个对象,
这个过程是由我们自己来控制的,而控制反转就把new对象的工交给了Spring容器。

形象的举例就是:
通常情况下,假如你有一天在家里口渴了,要喝水,那么你可以到你小区的小卖部去,告诉他们,你需要一瓶水,然后小卖部给你一瓶水!这本来没有太大问题,关键是如果小卖部很远,那么你必须知道:从你家如何到小卖部;小卖部里是否有你需要的水;你还要考虑是否开着车去;等等等等,也许有太多的问题要考虑了。也就是说,为了一瓶水,你还可能需要依赖于车等等这些交通工具或别的工具,问题是不是变得复杂了?那么如何解决这个问题呢?

解决这个问题的方法很简单:小卖部提供送货上门服务,凡是小卖部的会员,你只要告知小卖部你需要什么,小卖部将主动把货物给你送上门来!这样一来,你只需要做两件事情,你就可以活得更加轻松自在:
第一:向小卖部注册为会员。
第二:告诉小卖部你需要什么。

这和Spring的做法很类似!Spring就是小卖部,你就是A对象,水就是B对象
第一:在Spring中声明一个类:A
第二:告诉Spring,A需要B

1.2、 IOC的主要实现方式

IOC的主要实现方式有依赖注入。

依赖注入

依赖注入,组件不做定位查询,只提供标准的Java方法让容器去决定依赖关系。容器全权负责组件的装配,把符合依赖关系的对象通过Java Bean属性或构造方法传递给需要的对象。

1.2.1、 IoC容器

IoC容器:具有依赖注入功能的容器,可以创建对象的容器。IoC容器负责实例化、定位、配置应用程序中的对象并建立这些对象之间的依赖。

1.2.2 、依赖注入

DI,英文全称,Dependency Injection,意为依赖注入。

依赖注入:由IoC容器动态地将某个对象所需要的外部资源(包括对象、资源、常量数据)注入到组件(Controller, Service等)之中。简单点说,就是IoC容器会把当前对象所需要的外部资源动态的注入给我们。

Spring依赖注入的方式主要有四个,基于注解注入方式、set注入方式、构造器注入方式、静态工厂注入方式。推荐使用基于注解注入方式,配置较少,比较方便。

1.2.2.1、基于注解注入方式

服务层代码

@Service

public class AdminService {

//code

}

控制层代码

@Controller

@Scope("prototype")

public class AdminController {

@Autowired

private AdminService adminService;

//code

}
@Autowired与@Resource区别

@Autowired与@Resource都可以用来装配Bean,都可以写在字段、setter方法上。他们的区别是:

@Autowired默认按类型进行自动装配(该注解属于Spring),默认情况下要求依赖对象必须存在,如果要允许为null,需设置required属性为false,例:@Autowired(required=false)。如果要使用名称进行装配,可以与@Qualifier注解一起使用。

@Autowired

@Qualifier("adminService")

private AdminService adminService;

@Resource默认按照名称进行装配(该注解属于J2EE),名称可以通过name属性来指定。如果没有指定name属性,当注解写在字段上时,默认取字段名进行装配;如果注解写在setter方法上,默认取属性名进行装配。当找不到与名称相匹配的Bean时,会按照类型进行装配。但是,name属性一旦指定,就只会按照名称进行装配。

@Resource(name = "adminService")

private AdminService adminService;

除此之外,对于一些复杂的装载Bean的时机,比如我们需要根据配置装载不同的Bean,以完成不同的 *** 作,可以使用getBean(“beanID”)的方式来加载Bean。

通过BeanID加载Bean方法如下:

@Component

public class BeanUtils implements ApplicationContextAware {

private static ApplicationContext applicationContext;

@Override

public void setApplicationContext(ApplicationContext applicationContext) {

if (BeanUtils.applicationContext == null) {

BeanUtils.applicationContext = applicationContext;

}

}

public static ApplicationContext getApplicationContext() {

return applicationContext;

}

public static Object getBean(String id) throws Exception {

try {

return applicationContext.containsBean(id) ? applicationContext.getBean(id) : null;

} catch (BeansException e) {

e.printStackTrace();

throw new Exception("not found bean id: " + id);

}

}

}

我们在需要装载Bean的地方调用该方法即可

public class baseController {

protected IService loadService(String id) throws Exception {

IService iService = (IService) BeanUtils.getBean(id);

if (iService != null) {

return iService;

} else {

throw new Exception("加载Bean错误");

}

}

}
1.2.2.2、属性setter注入
//创建类A
public class A {
    public A() {
        System.out.println("正在初始化类A,调用无参构造器A。。。");
    }
    public void print() {
        System.out.println("调用了类A的print方法。。。");
    }
}
//创建类B
public class B {
    private A a;
    public void setA(A a) {
        this.a = a;
    }
    public void print() {
        a.print();
    }
}
//配置Beans.xml
    
    
        
    
//测试
    @Test
    public void test() {
        B b = (B) context.getBean("b");
        b.print();
    }

构造构造器注入

//配置Beans.xml
    
    
        
    
//测试
    @Test
    public void test() {
        B b = (B) context.getBean("b");
        b.print();
    }
1.2.2.3、静态工厂方式实例化
//创建工厂类
public class MyBeanFactory {
    public static A createCoffer() {
        return new A();
    }
}
//配置Beans.xml

//测试
    @Test
    public void test() {
        A a = (A) context.getBean("a");
    }
1.2.2.4、实例工厂实例化
//创建工厂类
public class MyBeanFactory {
    public MyBeanFactory() {
        System.out.println("A工厂实例化中。。。");
    }
    public A createBean() {
        return new A();
    }
}
//配置Beans.xml
    
    
//测试
    @Test
    public void test() {
        A a = (A) context.getBean("a");
    }
IoC 解决了什么问题

IoC 的思想就是两方之间不互相依赖,由第三方容器来管理相关资源。这样有什么好处呢?

1、对象之间的耦合度或者说依赖程度降低;
2、资源变的容易管理;比如你用 Spring 容器提供的话很容易就可以实现一个单例。

例如:现有一个针对 User 的 *** 作,利用 Service 和 Dao 两层结构进行开发

在没有使用 IoC 思想的情况下,Service 层想要使用 Dao 层的具体实现的话,需要通过 new 关键字在UserServiceImpl 中手动 new 出 IUserDao 的具体实现类 UserDaoImpl(不能直接 new 接口类)。

很完美,这种方式也是可以实现的,但是我们想象一下如下场景:

开发过程中突然接到一个新的需求,针对对IUserDao 接口开发出另一个具体实现类。因为 Server 层依赖了IUserDao的具体实现,所以我们需要修改UserServiceImpl中 new 的对象。如果只有一个类引用了IUserDao的具体实现,可能觉得还好,修改起来也不是很费力气,但是如果有许许多多的地方都引用了IUserDao的具体实现的话,一旦需要更换IUserDao 的实现方式,那修改起来将会非常的头疼。


使用 IoC 的思想,我们将对象的控制权(创建、管理)交有 IoC 容器去管理,我们在使用的时候直接向 IoC 容器 “要” 就可以了

面试怎么回答:

IOC是spring的两大核心概念之一,IOC给我们提供了一个IOCbean容器,这个容器会帮我们自动去创建对象,不需要我们手动创建,IOC实现创建的通过DI(Dependency Injection 依赖注入),我们可以通过写Java注解代码或者是XML配置方式,把我们想要注入对象所依赖的一些其他的bean,自动的注入进去,他是通过byName或byType类型的方式来帮助我们注入。正是因为有了依赖注入,使得IOC有这非常强大的好处,解耦。

可以举个例子,JdbcTemplate 或者 SqlSessionFactory 这种bean,如果我们要把他注入到容器里面,他是需要依赖一个数据源的,如果我们把JdbcTemplate 或者 Druid 的数据源强耦合在一起,会导致一个问题,当我们想要使用jdbctemplate必须要使用Druid数据源,那么依赖注入能够帮助我们在Jdbc注入的时候,只需要让他依赖一个DataSource接口,不需要去依赖具体的实现,这样的好处就是,将来我们给容器里面注入一个Druid数据源,他就会自动注入到JdbcTemplate如果我们注入一个其他的也是一样的。比如说c3p0也是一样的,这样的话,JdbcTemplate和数据源完全的解耦了,不强依赖与任何一个数据源,在spring启动的时候,就会把所有的bean全部创建好,这样的话,程序在运行的时候就不需要创建bean了,运行速度会更快,还有IOC管理bean的时候默认是单例的,可以节省时间,提高性能。

2、 AOP 2.1、AOP简单理解

AOP:即面向切面编程

面向切面编程(AOP)就是纵向的编程。比如业务A和业务B现在需要一个相同的 *** 作,传统方法我们可能需要在A、B中都加入相关 *** 作代码,而应用AOP就可以只写一遍代码,A、B共用这段代码。并且,当A、B需要增加新的 *** 作时,可以在不改动原代码的情况下,灵活添加新的业务逻辑实现。

能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。
Spring AOP是基于动态代理:如果代理类是实现了接口的类型,那么Spring将会用jdk的Proxy,如果代理类没有实现接口,那么将会使用CJlib的动态代理生成代理类的子类,其底层是使用了字节码 *** 作(ASM)技术。

在实际开发中,比如商品查询、促销查询等业务,都需要记录日志、异常处理等 *** 作,AOP把所有共用代码都剥离出来,单独放置到某个类中进行集中管理,在具体运行时,由容器进行动态织入这些公共代码。

AOP主要一般应用于签名验签、参数校验、日志记录、事务控制、权限控制、性能统计、异常处理等。

2.2、 AOP涉及名词

切面(Aspect):共有功能的实现。如日志切面、权限切面、验签切面等。在实际开发中通常是一个存放共有功能实现的标准Java类。当Java类使用了@Aspect注解修饰时,就能被AOP容器识别为切面。

通知(Advice):切面的具体实现。就是要给目标对象织入的事情。以目标方法为参照点,根据放置的地方不同,可分为前置通知(Before)、后置通知(AfterReturning)、异常通知(AfterThrowing)、最终通知(After)与环绕通知(Around)5种。在实际开发中通常是切面类中的一个方法,具体属于哪类通知,通过方法上的注解区分。

连接点(JoinPoint):程序在运行过程中能够插入切面的地点。例如,方法调用、异常抛出等。Spring只支持方法级的连接点。一个类的所有方法前、后、抛出异常时等都是连接点。

切入点(Pointcut):用于定义通知应该切入到哪些连接点上。不同的通知通常需要切入到不同的连接点上,这种精准的匹配是由切入点的正则表达式来定义的。

比如,在上面所说的连接点的基础上,来定义切入点。我们有一个类,类里有10个方法,那就产生了几十个连接点。但是我们并不想在所有方法上都织入通知,我们只想让其中的几个方法,在调用之前检验下入参是否合法,那么就用切点来定义这几个方法,让切点来筛选连接点,选中我们想要的方法。切入点就是来定义哪些类里面的哪些方法会得到通知。

目标对象(Target):那些即将切入切面的对象,也就是那些被通知的对象。这些对象专注业务本身的逻辑,所有的共有功能等待AOP容器的切入。

代理对象(Proxy):将通知应用到目标对象之后被动态创建的对象。可以简单地理解为,代理对象的功能等于目标对象本身业务逻辑加上共有功能。代理对象对于使用者而言是透明的,是程序运行过程中的产物。目标对象被织入共有功能后产生的对象。

织入(Weaving):将切面应用到目标对象从而创建一个新的代理对象的过程。这个过程可以发生在编译时、类加载时、运行时。Spring是在运行时完成织入,运行时织入通过Java语言的反射机制与动态代理机制来动态实现。

AOP 解决了什么问题

通过上面的分析可以发现,AOP 主要用来解决:在不改变原有业务逻辑的情况下,增强横切逻辑代码,根本上解耦合,避免横切逻辑代码重复。

AOP 为什么叫面向切面编程

切 :指的是横切逻辑,原有业务逻辑代码不动,只能 *** 作横切逻辑代码,所以面向横切逻辑

面 :横切逻辑代码往往要影响的是很多个方法,每个方法如同一个点,多个点构成一个面。这里有一个面的概念

Spring AOP 和 AspectJ AOP 有什么区别?

Spring AOP 属于运行时增强,而 AspectJ 是编译时增强。 Spring AOP 基于代理(Proxying),而 AspectJ 基于字节码 *** 作(Bytecode Manipulation)。

Spring AOP 已经集成了 AspectJ ,AspectJ 应该算的上是 Java 生态系统中最完整的 AOP 框架了。AspectJ 相比于 Spring AOP 功能更加强大,但是 Spring AOP 相对来说更简单,

如果我们的切面比较少,那么两者性能差异不大。但是,当切面太多的话,最好选择 AspectJ ,它比Spring AOP 快很多。

3、SpringMVC:

MVC是一种设计模式,M(模型),V(视图),C(控制)分层开发。在SpringMVC中我们一般将项目分为四层,业务处理层(Service),数据库 *** 作层(Dao),实体层(Entity),控制层(Controller)。

SpringMVC的工作原理:
在SpringMVC中有一个重要的中央控制器dispatcherServlet,或者叫做中央分发器,他负责接收前端请求,返回结果映射。其步骤如下:

1、浏览器发送请求,tomcat接收到请求之后传给了dispatcherServlet。
2、dispatcher传给了HandlerMapping处理器映射器将将会根据url解析出映射的handler。
3、HandlerAdapter处理器适配器将会调用映射的handler返回一个ModelAndView对象,包括一个Model和View对象。Model是返回的数据,View是逻辑上的View。
4、ViewResover视图解析器将会解析根据逻辑的VIew解析出实际的View。
5、dispatcherServlet将Model传给View。
6、dispatcherServlet返回View给浏览器。
Spring框架用了那些设计模式?

工厂设计模式 : Spring使用工厂模式通过 BeanFactory、ApplicationContext 创建 bean 对象。
代理设计模式 : Spring AOP 功能的实现。
单例设计模式 : Spring 中的 Bean 默认都是单例的。
模板方法模式 : Spring 中 jdbcTemplate、hibernateTemplate 等以 Template 结尾的对数据库 *** 作的类,它们就使用到了模板模式。
包装器设计模式 : 我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。
观察者模式: Spring 事件驱动模型就是观察者模式很经典的一个应用。
适配器模式 :Spring AOP 的增强或通知(Advice)使用到了适配器模式、spring MVC 中也是用到了适配器模式适配Controller。

DAO层,Service层,Controller层、View层

DAO层,Service层,Controller层、View层

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/4667523.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-06
下一篇 2022-11-06

发表评论

登录后才能评论

评论列表(0条)

保存