基于注解的Spring(IOC+AOP)

news2024/11/19 5:50:43

目录

这是基于黑马Spring的笔记

写再前面

开始

 @Component(value=bean的名称) 

componet衍生出的3个注解

Bean内部的属性进行注入

非自定义的Bean管理

使用配置类完全替代XML配置文件

 配置类中的注解

spring中的其他注解(偶尔会用到)

 Spring注解的解析原理

spring使用注解整合第三方框架mybatis

XML和@Mapperscan注解整合Mybatis的底层原理:

@import整合第三方框架

基于注解的AOP


写再前面

IOC和AOP都是面向切面编程(Aspect-Oriented Programming)的实现方法。

它们提供了一种抽象机制,可以实现在程序运行期动态地将额外功能插件到现有代码中。

IOC全称是Inversion of Control,即控制反转。它是Spring框架的核心,可以实现对象之间的依赖注入。基于IOC,对象的依赖关系由容器在运行期决定,完成对象的装配。这可以降低对象之间的耦合,使设计更加灵活。

AOP全称是Aspect-Oriented Programming,即面向切面编程。它可以实现在不修改源代码的情况下,为程序动态添加功能。在程序执行过程中,AOP可以在合适的连接点(如方法调用前/后),插入切面来修改程序逻辑。这有助于实现诸如日志、安全等通用功能,而不用在业务逻辑代码中夹杂各种非业务逻辑。

简单来说,IOC和AOP的区别在于:

- IOC 注重在对象创建与依赖注入,目的在于降低耦合、增强灵活性。它由容器在运行期决定对象依赖关系。

- AOP 注重在动态插入切面来影响程序运行逻辑,目的在于实现通用功能而不改变原有代码。它允许在程序运行期间插入切面来修改逻辑。所以,尽管IOC和AOP都属于面向切面编程范畴,但侧重点不同:

- IOC侧重对象的依赖关系注入,实现解耦和灵活设计。

- AOP侧重在运行期动态修改程序逻辑,实现通用功能的插入。两者都是实现高内聚低耦合的有效手段,广泛应用在企业级框架与项目中。Spring就是典型代表,它同时采用IOC和AOP实现解耦、通用功能和业务逻辑分离。

通过b站上的黑马的spring课程做的笔记。

Spring 3.0时代,进入全注解时代。S

pringboot就是一个几乎零配置的企业级开发框架。

开始

 在不使用配置类时在applicationcontext配置文件中引入(后面也可以完全以注解的方式代替配置类)

    <!-- 配置扫描组件所在的包 -->
    <context:component-scan base-package="demo.pojo"/>

 @Component(value=bean的名称) 

若没有value则默认是类名的小写作为beanname.

测试用例

package demo.pojo;


import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

@Component(value = "yzh")
@Scope("singleton")
@Lazy(false)

public class user {


    public user() {
        System.out.println("无参构造执行");
    }


    @PostConstruct
    void init()
    {
        System.out.println("实例化后执行");
    }

    @PreDestroy
    void destroy()
    {
        System.out.println("bean销毁前执行");
    }

}

componet衍生出的3个注解

 既不属于web层,Service层,Dao层,普遍使用@Component.

Bean内部的属性进行注入

 

 @Value 在bean内部属性注入时,可直接放在bean的属性上,也可以放在bean的set方法中.

@Autowired 首先会根据类型进行注入,若发现有多个类型匹配,则根据注入的属性名进行匹配,若依然匹配不成功则提示报错。(在这种情况下,可以结合@Autowired,根据名称进行注入)

 @Resource 不指定名称时等同于@Autowired;指定名称时根据名称进行注入。

@Autowired扩展:

值得注意的是,当@AutoWired注解在方法上时,会根据参数的名字或者是集合中的类型进行注入(这种情况若发现有多个类型时,会全部注入到集合当中。)

非自定义的Bean管理

非自定义Bean不能像自定义Bean一样使用@Compnent进行管理,非自定义的Bean需要通过工厂的方式进行实例化,使用@Bean标注方法即可,@Bean的属性为beanName.若不加beanname则默认为方法名。(如以下的dataSource)。因为需要@Bean注解被扫描到,所以非自定义的bean所在的类必须被Spring容器管理。这也是为什么以下的'other'必须加component的原因。

见实例

package demo.otherbean;


import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;

@Component
public class other {




    @Bean("druid")
    public DataSource dataSource()
    {
        DruidDataSource   druid = new DruidDataSource();

        return  druid;
    }
}

当非自定义的Bean需要参数注入时:

基本数据类型 :@Value (位置放在参数内部)

引用类型:

1.根据名称进行注入时:@Qualifier("参数名称")此处可以省略@Autowired(这点和自定义bean的@Qualifier结合@Autowired注入时不同)

2.根据类型进行注入时: 可不加任何注解。如下面的userservice.

使用配置类完全替代XML配置文件

通过以上的注解已经能够代替bean标签,在使用配置文件时通过ClassPathXmlApplicationContext类去加载我们的配置文件;


        ClassPathXmlApplicationContext context=
                new  ClassPathXmlApplicationContext("applicationcontext.xml");

而使用配置类时,则用

AnnotationConfigApplicationContext 去加载配置类。

        ApplicationContext context=
                new AnnotationConfigApplicationContext(springconfig.class);

 配置类中的注解

@ComponentScan相当于

<context:component-scan base-package="demo.otherbean"/>

@ComponentScan相当于

<context:property-placeholder location="classpath:test.properties"/>

若有多项扫描项或需要读取的配置文件,则用数组形式。参考以下实例

package demo.config;


import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

@Configuration  //标明这是一个配置类 交给Spring容器去管理
@ComponentScan({"demo.pojo","demo.otherbean"})
@PropertySource({"test.properties"})
public class springconfig {


}

@import 用于加载其他的配置文件,用于替代原xml标签中的<import>

spring中的其他注解(偶尔会用到)

 

 Spring注解的解析原理

 XML方式的组件扫描:在Spring容器创建时,使用XML命名空间的形式扫描指定的包以及子包下的类,识别注解,创建Beandefinition 存储到beandefinitionMap中最终进入单例池。

注解方式如@ComponentScan的组件扫描:通过BeanFactoryProcessor(bean工厂处理器)扫描注解创建Beandefinition存储到beandefinitionMap中最终进入单例池。而Bean的属性注入则通过BeanPostProcessor(Bean后处理器)扫描@Autowired等注解进行属性的注入。

spring使用注解整合第三方框架mybatis

原来的XML方式整合:

步骤

  1. 需要创建SqlSessionFactoryBean,而SqlSessionFactoryBean需要注入一个引用类型为DataSource。
  2. 创建 DataSource。DataSource属于非自定义的bean,需要通过工厂方法的方式进行注入,且该工厂方法所在的类需要被Spring容器管理.

jdbc.properties 连接数据库的配置信息:

 在这里发现了数据的格式问题,我在另一个项目中用yaml文件配置.在yaml文件里数据库的密码如上的061457需要加引号才能连接成功,而在.properties的配置文件中不能加引号才连接成功。(目前认为应该是配置文件的约束问题)

 

目录结构:

关于配置是否成功:

有个mybatisX的插件,一般来说xml文件能找到其对应的mapper接口映射文件则没什么问题。

核心注解

@MapperScan扫描Mapper接口

@PropertySource 加载配置文件

package demo.config;


import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

import javax.sql.DataSource;

@Configuration  //标明这是一个配置类 交给Spring容器去管理
@ComponentScan({"demo.pojo","demo.otherbean"})
@PropertySource({"jdbc.properties"})
@MapperScan("demo.mapper")
public class springconfig {



    @Bean
    public DataSource dataSource(
            @Value("${jdbc.username}")  String username,
            @Value("${jdbc.drive}") String drive,
            @Value("${jdbc.url}") String url,
            @Value("${jdbc.pwd}") String pwd

    )
    {


        System.out.println(username+":"+drive+":"+url+":"+pwd);
        DruidDataSource druid = new DruidDataSource();
        druid.setDriverClassName(drive);
        druid.setUrl(url);
        druid.setUsername(username);
        druid.setPassword(pwd);


        return  druid;
    }


    @Bean
    public SqlSessionFactoryBean  SqlSessionFactoryBean(DataSource dataSource) //此处注入不加注解则通过类型进行注入
    {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);

        return sqlSessionFactoryBean;
    }

}

XML和@Mapperscan注解整合Mybatis的底层原理:

简单的说:

都是扫描Mapper接口(比如以上的UserMapper),注册MapperFactorybean.而底层的MapperFactoryBean的getobject方法返回接口的实现。只不过入口不同,XML方式直接去配置MapperScannerConfig类,而注解通过导入MapperScannerRegister,通过MapperScannerRegister去注册MapperScannerConfig

@import整合第三方框架

        Spring与Mybatis的注解方式整合有个重要的技术点就是@Import,第三方框架与Spring整合很多都是凭借自定义标签完成的,而第三方框架与Spring整合注解方式很多是靠@Import注解完成的。

比如在myatis的@MapperScan注解中

 开发用的最多的还是导入普通的配置类。而需要整合自定义的第三方框架时,使用@Import导入实现ImportSelector接口的类以及实现ImportBeanDefinitionRegistrar接口的类就比较普遍了。

    下面给出一个实例(自定义注解导入实现ImportBeanDefinitionRegistrar接口的类)

自定义注解

package demo.config;


import org.springframework.context.annotation.Import;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Import(MyImportBeanDefinitionRegistrar.class)
public @interface Mymapper {



}

基于注解的AOP

Spring框架的AOP支持两种代理方式:基于JDK动态代理和基于CGLIB的代码生成代理。

  1. 基于JDK动态代理:使用JDK动态代理进行AOP代理时,目标对象必须实现至少一个接口。Spring会为实现了指定接口的目标对象动态生成一个代理对象,并在代理对象中拦截对目标方法的调用,并执行相应的增强逻辑。由于JDK动态代理是基于接口进行代理的,因此对于没有实现任何接口的目标类,无法使用JDK动态代理进行代理。

  2. 基于CGLIB的代码生成代理:如果目标对象没有实现任何接口,则Spring将使用CGLIB库来为该对象创建一个子类,并将代理逻辑织入到子类中。与JDK动态代理不同,CGLIB代理是通过生成目标类的子类来实现的,因此它能够代理没有实现任何接口的类。但是,由于CGLIB是通过生成目标类的子类来实现代理,所以对于final方法、private方法等无法覆盖的方法,也无法使用CGLIB来进行代理。

总之,Spring框架的AOP支持多种代理方式,在选择代理方式时需要根据目标对象是否实现接口、要代理的方法类型(final方法、private方法等)以及代理性能等因素来进行选择。通常情况下,如果目标对象实现了接口,则优先使用基于JDK动态代理的方式;否则,使用基于CGLIB的代码生成代理。

开启自动代理的注解,默认为基于JDK的动态代理,一般在配置类加上这个注解(因为基于注解开发,肯定要创建一个配置类)我发现无论有没有实现接口的类以上面两种方式(JDK的动态代理,CJLIB)都能实现AOP.

@EnableAspectJAutoProxy

基于CJlib的代理

@EnableAspectJAutoProxy(proxyTargetClass=true)

 AOP的相关Maven依赖


<!--提供AOP基本模块的功能-->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aop</artifactId>
                <version>5.3.20</version>
            </dependency>


<!--     AspectJ 是一种面向切面编程(AOP)框架,aspectjweaver 提供了实现基于 AspectJ 的 AOP 功能所需的运行时依赖关系。-->
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjweaver</artifactId>
                <version>1.9.6</version>
            </dependency>
<!--    spring-aspects 为 Spring AOP 提供了额外的方面(Aspect),可以用于事务管理等功能。-->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aspects</artifactId>
                <version>5.3.16</version>
            </dependency>

通知类

package demo.advise;


import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;

@EnableAspectJAutoProxy
@Component
@Aspect
public class advise {

@Pointcut("execution( *  demo.otherbean.*.*(..))")
public  void myponitcut(){} //切点表达式的抽取


    @Before("myponitcut()")//切点表达式,demo包下的otherbean包下的所有类的所有方法的所有参数为切点
    public  void beforeAdvise(JoinPoint joinPoint)
    {

        System.out.println("当前目标对象是:"+joinPoint.getTarget());
        System.out.println("表达式:"+joinPoint.getStaticPart());

        System.out.println("前置通知");
    }


    @After("myponitcut()")//切点表达式,demo包下的otherbean包下的所有类的所有方法的所有参数为切点
    public  void afterAdvise(JoinPoint joinPoint)
    {

        System.out.println("当前目标对象是:"+joinPoint.getTarget());
        System.out.println("表达式:"+joinPoint.getStaticPart());

        System.out.println("后置通知");
    }
}

 通过这个通知类可以看到:

它可以带参数为JoinPoint(切点),更可以通过其getTarget方法拿到切点所在的类对象。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/641447.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java Supervisor RPC2 接口对接

1.引入xmlrpc-client 如果是C#语言&#xff0c;请参考《C#对接supervisor XML-RPC API 实现进程控制》 如何安装Supervisor&#xff0c;请参考《Linux进程守护—Supervisor&#xff08;ubuntu&#xff09;》 如果是Maven项目&#xff0c;则在pom.xml引入jar包 <dependenc…

详解CSS中的flex布局

详解CSS中的flex布局 1、概念2、容器属性2.1 flex-direction2.2 flex-wrap2.3 flew-flow2.4 justify-content2.5 align-items2.6 align-content 3、元素属性3.1 order3.2 flex-grow3.3 flex-shrink3.4 flex-basis3.5 flex3.6 align-self 1、概念 弹性盒子&#xff08;display: …

如何系列 JMeter如何录制脚本

文章目录 方式1. 手动编写2. JMeter自带录制功能3. Fiddler录制4. Badboy录制5. Blazemeter录制 总结和使用感受 方式 1. 手动编写 最原始的方式&#xff0c;在线程组中根据研发提供的接口文档和浏览器的Network请求一个个手动录入&#xff0c;它可以提供更大的灵活性和控制力…

PostgreSQL 中的虚拟文件描述符

由于每个操作系统限制了一个进程能打开的文件数&#xff08;例如&#xff1a;ubuntu 为1024&#xff09;&#xff0c;因此进程能获得的文件描述符是有限的。对于经常需要打开许多文件的数据库进程来说&#xff0c;很容易会超过操作系统对于文件描述符数量的限制。 为解决这个问…

如何写好一份解决方案

1、前言 我们在日常工作中会不可避免要去编写各种方案&#xff0c;如技术方案、建设方案、项目建议书、实施方案、规划方案、解决方案等。 我们去浏览华为、阿里、腾讯、IBM、海尔等公司的官网&#xff0c;可以看到在首页比较显眼的位置&#xff0c;都有解决方案的入口&#…

Postcat X APISIX 合作插件 :一键同步,轻松配置到 APISIX

近日&#xff0c;云流科技&#xff08;广州&#xff09;有限公司&#xff08;简称“Eolink”&#xff09;旗下的开源 API 管理工具 Postcat 和深圳支流科技有限公司&#xff08;简称“API7 支流科技”&#xff09;在各自擅长的领域携手合作&#xff0c;推出了 Postcat & Ap…

R语言 tidyverse系列学习笔记(系列4)PlantGrowth - percentage table

本篇学习数据分析&#xff0c; Excel 表格制作 Task&#xff1a; 创建一个 行 百分比 表格 row percentage table 先看一下 PlantGrowth 数据集 library(dplyr)data("PlantGrowth") view(PlantGrowth)给数据集新加一列 weight_cat &#xff0c;并用 case_when 自定…

【React】: React的生命周期

概述 生命周期的每个阶段总是伴随着一些方法的调用&#xff0c;这些方法就是生命周期的钩子函数 钩子函数的作用&#xff1a;为开发人员在不同操作阶段提供了十几 只有 类组件 才有生命周期 生命周期的图片&#xff1a; 同时有&#xff1a; 1.1 创建时 的生命周期执行顺序 编写…

计划任务使用介绍

作者:lly 文章目录 前言一、使用说明1.1 发布模型1.2 创建并设置计划任务1.3 开启计划任务1.4 管理计划任务 二、结语 前言 iServer 11i(2023)对于处理自动化服务新增计划任务功能&#xff0c;该功能支持定时触发和监听文件变化触发执行模型&#xff0c;因此计划任务适用于以下…

Vite构建工具下Tinymce踩坑指南

背景 "vue": "^3.2.41","vite": "^3.2.3","tinymce": "^6.4.2","tinymce/tinymce-vue": "^5.1.0",坑1: 找不到zh-Hans.js等配置的文件 使用Tinymce需要配置中文汉化包、样式等。这些文件都是…

安全问题我们需要重视,立刻升级fastjson2

一、前言 小伙伴大家好&#xff0c;我是开源字节快速开发平台的作者。fastjson2.0 是fastjson的重要升级&#xff0c;目标是为下一个十年提供一个高性能的JSON库&#xff0c;同一套API支持JSON/JSONB两种协议。 近期fastjson 再报安全漏洞&#xff0c;直接给我们发送了高危告…

FastReport 2023.2新版, Delphi 和 Lazarus 核心产品将统一整合, 一起来看!

FastReport 是功能齐全的报表控件&#xff0c;可以帮助开发者可以快速并高效地为.NET&#xff0c;VCL&#xff0c;COM&#xff0c;ActiveX应用程序添加报表支持&#xff0c;由于其独特的编程原则&#xff0c;现在已经成为了Delphi平台最优秀的报表控件&#xff0c;支持将编程开…

风景类Midjouney prompt提示词

稳定输出优美风景壁纸的Midjouney prompt提示词。 1\在夏夜&#xff0c;有淡蓝色的星空&#xff0c;海边&#xff0c;流星&#xff0c;烟花&#xff0c;海滩上全是蓝色的玫瑰和绿色的植物&#xff0c;由Ivan Aivazovsky和Dan Mumford&#xff0c;趋势在cgsociety&#xff0c;柔…

HEIC→JPG

问题描述&#xff1a;图片格式由HEIC转JPG 解决办法&#xff1a;在网上找一个在线图片转格式的软件

我理解的参与开源贡献

坐标上海的E人&#xff0c;还在新手村练级的前端开发。曾闯荡过教育培训和零售管理行业&#xff0c;经历过大公司、外企&#xff0c;也和朋友的工作室合作过&#xff0c;斩获过一些能吓唬人的标签。好奇心很足&#xff0c;精力也很充沛&#xff0c;代码世界就是我现实生活中的霍…

【前后端实现文件下载或浏览】

前后端实现文件下载或浏览 背景前端后端java其他IO流分两种&#xff1b;字符流&字节流 背景 前端html\js\css,使用a标签或者iframe,笔者使用window.open(url)—重新打开标签页地址栏显示的接口路径;后端返回客户端[HttpServletResponse] 文件流&#xff08;以附件的方式[a…

建设现代化智慧十防档案室所需要的技术性方案

一、库房温湿度对档案的影响 库房的温湿度&#xff0c;过高过低都会影响档案制成材料的耐久性。高温高湿会加速纸张的老化水解&#xff0c;使危害档案制成材料的霉菌、细菌繁殖&#xff0c;并增强光化作用&#xff0c;使有害气体、灰尘吸附能力增大。但低温低湿会使纸张变脆&a…

VXLAN 主机VTEP(EVPN)

EVE环境模拟搭建一个基于主机VTEP的VXLAN数据中心网络。 实验里vtep是在linux主机上&#xff0c;同时linux主机还得有路由功能使VTEP的端点IP可达&#xff0c;所以两台linux服务器需要安装FRR。 数据转发平面使用VXLAN封装&#xff1b;在控制平面我打算选择使用EVPN和OVN两种不…

数据中台的商机

阿里拆中台了&#xff0c;很多人来问数据中台还要不要的问题&#xff0c;我认为中台总是要有的&#xff0c;无非是薄厚的问题。然后又有人来问数据中台价值创造的问题&#xff0c;这个其实是数据中台最核心的问题&#xff0c;我就来正式聊一聊&#xff0c;里面有很多的批判&…

T900:可以完美替代P900的国产900MHz无线跳频模块

目录 国产T900模块及其系列成品 T900模块 T900成品 国产T900模块及其系列成品 T900模块及其系列成品&#xff0c;是专门针对无人机及机器人行业设计的&#xff0c;尺寸小、性能优越&#xff0c;可以完美替代microhard的P900产品。下面向大家介绍下T900的相关情况&#xff1…