Spring(IOC、DI、AOP、注解)

本文深入介绍了Spring框架的核心功能,包括依赖注入、面向切面编程等关键特性,并详细解释了Spring的各种模块及其应用场景。
  • Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器(框架)。
  • Spring 的七大模块:

    • Spring Core:核心类库,所有功能都依赖于该类库,提供IOC和DI服务;
    • Spring AOP:是Spring的AOP库,提供了AOP(拦截器)机制,并提供常见的拦截器,供用户自定义和配置。
    • Spring ORM:提供对常用ORM框架的管理和支持,hibernate、mybatis等。
    • Spring DAO:Spring提供对JDBC的支持,对JDBC进行封装。
    • Spring Web:提供了基本的面向Web的综合特性,提供对常见框架如Struts2的支持。
    • Spring Context:Context模块提供框架式的Bean的访问方式,其它程序可以通过Context访问Spring的Bean资源,相当于资源注入。
    • Spring MVC:MVC模块为spring提供了一套轻量级的MVC实现,即Spring MVC。
  • Spring 的优点:

    • 1、Spring属于低侵入式设计,代码的污染极低;
    • 2、Spring的DI机制将对象之间的依赖关系交由框架处理,减低组件的耦合性;
    • 3、Spring提供了AOP技术,支持将一些通用任务,如安全、事务、日志、权限等进行集中式管理,从而提供更好的复用。
    • 4、Spring对于主流的应用框架提供了集成支持。
    • IOC 让相互协作的组件保持松散的耦合,而 AOP 编程允许你把遍布于应用各层的功能分离出来形成可重用的功能组件。
  • IOC(控制反转):

    • 概念:

      • 即控制权的转移,将我们创建对象的方式反转了,以前对象的创建是由我们开发人员自己维护,包括依赖关系也是自己注入。使用了spring之后,对象的创建以及依赖关系可以由spring来完成,反转控制就是反转了对象的创建方式,从我们自己创建反转给了程序创建(spring)
    • 创建对象的方式:

      • 构造方法,

        • 无参构造:spring 通过字节码对象,拿到constructor.newInstance(),构造器创建;通过set方法注入属性
          • <bean id="stu" class="Student.Student" >
            • <property name="name" value="张三"></property> 属性用value;对象用ref,值为beas的id
          • </bean>
        • 有参构造:通过反射得到构造器,给构造方法赋值;beans.xml有三种写法:
          • 1、下标赋值:
            • <constructor-arg index="0" value="张三"></constructor-arg> 给构造方法第一个参数赋值
          • 2、参数名称赋值:
            • <constructor-arg name="name" value="张三"></constructor-arg>
          • 3、参数类型赋值:
            • <constructor-arg type="java.lang.String" value="张三"/>
      • 工厂方法模式,

        • <bean id="fa" class="Student.FactoryEntity"></bean> 通过工厂类的方法创建
        • <bean id="stu1" factory-bean="fa" factory-method="getInstance">
          • <constructor-arg name="str" value="student"></constructor-arg> str 为 getInstance 方法的参数名
        • </bean>
      • 静态工厂,

        • <bean id="stu2" class="Student.FactoryEntityStatic" factory-method="getStudentInstance"></bean> 通过工厂类的静态方法创建,不用反射
    • 获取对象:(通过 ApplicationContext 容器)

      • ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
      • Student stu = (Student) context.getBean("stu");
    • bean 属性的使用:

      • 1. abstract="true" (抽象);2. init-method="hi "(对象创建之后立刻调用);3. destroy-method="hi" (在关闭并销毁所有容器中的对象之前调用);
      • 4. scope五种作用域(bean的作用域):singleton(默认单例模式,多线程下不安全);prototype(多例模式);request、session;global Session(在一个全局的 Http Session 中,容器会返回该 Bean 的同一个实例,仅在 使用 portlet context 时有效。)
  • DI(依赖注入):

    • 概念:(向spring容器的索取)

      • 依赖注入是IOC的一种具体实现方式,它是通过IOC容器将一个对象所依赖的其他对象(依赖项)注入到该对象中的过程。
      • 依赖注入(Dependency Injection)和控制反转(Inversion of Control)是同一个概念。具体含义是:当某个角色(可能是一个Java实例,调用者)需要另一个角色(另一个Java实例,被调用者)的协助时,在 传统的程序设计过程中,通常由调用者来创建被调用者的实例。但在Spring里,创建被调用者的工作不再由调用者来完成,因此称为控制反转;创建被调用者 实例的工作通常由Spring容器来完成,然后注入调用者,因此也称为依赖注入。
    • 依赖注入的方式:

      • 1、构造方法注入:

        • <bean id="stu" class="Student.Student" >
          • <constructor-arg ref="beansid" ></constructor-arg >
        • </bean>
      • 2、setter 方法赋值 (静态工厂注入)(实例工厂):

        • <bean id="stu3" class="Student.Student">
          • <property name="name" value="lisi"></property> 忽略大小写比较setter;通过反射得到的方法,给方法赋值
          • <property name="repository" ref="myRepository" />
        • </bean>
      • 3、自动装配:

        • <bean id="StudentDao" class="Student.StudentDao"></bean>
        • <bean id="stuService" class="Student.StudentService" autowire="byType"></bean>
        • autowire 的使用:
          • byType:寻找容器里class为,当前bean属性类型的bean,并自动创建(要有无参构造)。如果有多个bean符合条件,则抛出错误。
          • byName:寻找容器里id为,当前bean属性参数的bean,并自动创建(要有无参构造)
          • constructor:寻找容器里id为,当前bean类构造方法的属性参数的bean,并自动创建(要有有参构造)
          • no:不装配
          • autodetect:首先尝试使用 constructor 来自动装配,如果无法工作,则使用 byType 方式。
      • 4、字段注入:

        • @Autowired
        • private MyRepository repository;
        • 通过直接注入字段的方式将依赖注入到目标Bean中。可以在字段上使用 @Autowired 注解进行注入。
        • 确保在配置文件中启用注解驱动:<context:annotation-config />
      • 5、方法注入:

        • @Autowired
        • public void setRepository(MyRepository repository) { this.repository = repository; }
        • 该方法在配置类中被调用,并返回所需的Bean实例。
      • 6、接口注入:

        • public class MyBean implements InitializingBean {
        • @Override
        • public void afterPropertiesSet() { // 在Bean初始化后执行的操作 }
        • }
        • 在Bean初始化后执行自定义初始化操作。
      • 复杂类型的注入(数组注入,list集合注入,map集合注入,properties注入)
  • AOP(面向切面编程):

    • 理解:

      • OOP面向对象,允许开发者定义纵向的关系,但并不适用于定义横向的关系,会导致大量代码的重复,而不利于各个模块的重用。
      • AOP,一般称为面向切面,作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),减少系统中的重复代码,降低了模块间的耦合度,提高系统的可维护性。可用于权限认证、日志、事务处理。
      • AOP实现的关键在于 代理模式,AOP代理主要分为静态代理和动态代理。静态代理的代表为AspectJ;动态代理则以Spring AOP为代表。
      • 1、AspectJ 是静态代理,也称为编译时增强,AOP框架会在编译阶段生成AOP代理类,并将AspectJ(切面)织入到Java字节码中,运行的时候就是增强之后的AOP对象。
      • 2、Spring AOP 使用的动态代理,所谓的动态代理就是说AOP框架不会去修改字节码,而是每次运行时在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。(在运行工程中,动态织入切面类代码)
      • 3、静态代理与动态代理区别在于生成AOP代理对象的时机不同,相对来说AspectJ的静态代理方式具有更好的性能,但是AspectJ需要特定的编译器进行处理,而Spring AOP则无需特定的编译器处理。
    • 名词的概念:

      • 1、连接点(Join point):目标对象中,所有可以增强的方法,就是spring允许你是通知(Advice)的地方,那可就真多了,基本每个方法的前、后(两者都有也行),或抛出异常是时都可以是连接点,spring只支持方法连接点。
      • 2、切点(Pointcut):切点用于定义 要对哪些Join point进行拦截。
        • 一个类里,有15个方法,那就有几十个连接点了对吧,但是你并不想在所有方法附近都使用通知,那么就用切点来定义这几个方法。
        • 切点分为execution方式和annotation方式。execution方式可以用路径表达式指定对哪些方法拦截,比如指定拦截add*、search*。annotation方式可以指定被哪些注解修饰的代码进行拦截。
      • 3、通知(Advice):指要在连接点(Join Point)上执行的动作,即增强的逻辑,比如权限校验和、日志记录等。
      • 4、目标对象(Target):包含连接点的对象,也称作被通知(Advice)的对象。 由于Spring AOP是通过动态代理实现的,所以这个对象永远是一个代理对象。
      • 5、代理(Proxy):将通知织入到目标对象之后形成的代理对象.
      • 6、切面(Aspect):切入点+通知————通知(Advice)说明了干什么的内容(即方法体代码)和什么时候干(什么时候通过方法名中的before,after,around等就能知道),切入点说明了在哪干(指定到底是哪个方法),切点表达式等定义。
      • 7、织入(Weaving):将通知应用到连接点形成切入点的过程。
        • 通过动态代理,在目标对象(Target)的方法(即连接点Join point)中执行增强逻辑(Advice)的过程。
        • 把切面应用到目标对象来创建新的代理对象的过程。
      • 8、引入(Introduction):添加额外的方法或者字段到被通知的类。Spring允许引入新的接口(以及对应的实现)到任何被代理的对象。
    • 通知(Advice)的类型:

      • 前置通知 (Before Advice):
        • 前置通知在目标方法(连接点Join point)执行之前执行。它主要用于执行一些预处理操作,例如权限检查、日志记录等。
      • 后置通知 (After Advice):(不论是正常返回还是异常退出)
        • 后置通知在目标方法执行之后执行。它可以用于执行一些清理工作,如资源释放、日志记录等。
      • 环绕通知 (Around Advice):
        • 环绕通知包围目标方法的执行。它可以在目标方法之前和之后执行自定义逻辑,还可以决定是否调用目标方法以及如何处理返回值。
      • 返回通知 (After Returning Advice):(如果连接点抛出异常,则不执行)
        • 返回通知在目标方法正常执行并返回结果后执行。它可以获取目标方法的返回值,对返回值进行处理,或记录方法的执行结果。
      • 异常通知 (After Throwing Advice):
        • 异常通知在目标方法抛出异常后执行。它用于处理异常情况,如发送通知、日志记录、或执行回滚操作。
    • 通知(Advice)的执行顺序:

      • 在同一个切面中,对于同一个切入点的不同通知方法,优先级从高到低分别是@Around、@Before、@After、@AfterReturning和@AfterThrowing。在进入切入点时,最高优先级的通知方法最先执行;在离开切入点时,最高优先级的通知方法最后执行。
      • around before advice;before advice;target method 执行;afterReturning advice;after advice;around after advice
  • 注解:

    • 什么是注解:

      • Java 注解就是代码中的一些特殊标记(元信息),用于在编译、类加载、运行时进行解析和使用,并执行相应的处理。它本质是继承了 Annotation 的特殊接口,其具体实现类是 JDK 动态代理生成的代理类,通过反射获取注解时,返回的也是 Java 运行时生成的动态代理对象 $Proxy1。通过代理对象调用自定义注解的方法,会最终调用 AnnotationInvocationHandler 的 invoke 方法,该方法会从 memberValues 这个Map中查询出对应的值,而 memberValues 的来源是Java常量池。
      • @ Target:标识注解可以修饰哪些地方,比如方法、成员变量、包等。
      • @ Retention:什么时候使用注解:SOURCE(编译阶段就丢弃) / CLASS(类加载时丢弃) / RUNTIME(始终不会丢弃)
        • 一般来说,我们自定义的注解都是 RUNTIME 级别的,因为大多数情况我们是根据运行时环境去做一些处理,一般需要配合反射来使用,因为反射是 Java 获取运行时的信息的重要手段。
      • @ Document:注解是否会包含在 javadoc 中。
      • @ Inherited:定义该注解与子类的关系,子类是否能使用。
      • 如何自定义注解 ?
        • ①创建一个自定义注解:与创建接口类似,但自定义注解需要使用 @interface
        • ② 添加元注解信息,比如 @Target、@Retention、@Document、@Inherited 等
        • ③ 创建注解方法,但注解方法不能带有参数
        • ④ 注解方法返回值为基本类型、String、Enums、Annotation 或其数组
        • ⑤ 注解可以有默认值;
    • Spring 常用注解:

      • 1、组件装配相关注解:
        • @Component 通用的组件注解,通常与其他注解一起使用;@Controller:控制层;@Service:业务层;@Repository:数据访问层
          • @Controller和@Service和@ Repository 是它的特殊情况
        • @Bean :导入第三方包里面的注解;
        • @Import :要导入到容器中的组件;
      • 2、 依赖注入相关注解 / 注入bean的注解:
        • @Resource: ByName装配 解耦好
        • @Autowired: ByType装配 兼容性好,多数用
          • 用于自动装配依赖。可以注解在字段、构造函数、Setter方法上。
          • 默认情况下它要求依赖对象必须存在;有个属性为required,可以配置为false;
        • @Qualifier:结合@Autowired使用,把Autowired转换成ByName方式,指定依赖的名称。
      • 3、Java配置类相关注解:
        • @Configuration :声明当前类为配置类;
        • @Bean :注解在方法上,声明当前方法的返回值为一个bean,替代xml中的方式;
        • @ComponentScan 用于对Component进行扫描;配置组件扫描的规则
      • 4、aop相关注解:
        • @Aspect:用于定义切面类,切面类中包含通知(Advice)方法。
          • <context:component-scan base-package="com.crx.anno"></context:component-scan>
            • <aop:aspectj-autoproxy></aop:aspectj-autoproxy> 切面代理,自动代理模式 使aop的注解可用
        • @Pointcut:用于定义切点,即指定一组连接点,通知将在这些连接点上执行。
        • @Order:用于控制通知的执行顺序。数字越小,执行顺序越早。
  • 参考:
    • 原文链接:https://blog.youkuaiyun.com/itcats_cn/article/details/81479185
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值