首页IT科技spring注解使用详解(spring注解)

spring注解使用详解(spring注解)

时间2025-08-04 21:52:00分类IT科技浏览4175
导读:Spring注解驱动...

Spring注解驱动

文章来源:yuque.com/zuihoudewu/java_note/gwtgt9#ip308

@Cofigretion(proxyBeanMethods = true)

标记在类上              ,告诉spring这是一个配置类

首先引出两个概念:Full 全模式                     ,Lite 轻量级模式

Full(proxyBeanMethods = true) :proxyBeanMethods参数设置为true时即为:Full 全模式              。 该模式下注入容器中的同一个组件无论被取出多少次都是同一个bean实例        ,即单实例对象       ,在该模式下SpringBoot每次启动都会判断检查容器中是否存在该组件 Lite(proxyBeanMethods = false) :proxyBeanMethods参数设置为false时即为:Lite 轻量级模式                      。该模式下注入容器中的同一个组件无论被取出多少次都是不同的bean实例                     ,即多实例对象               ,在该模式下SpringBoot每次启动会跳过检查容器中是否存在该组件 什么时候用Full全模式       ,什么时候用Lite轻量级模式? 当在你的同一个Configuration配置类中                     ,注入到容器中的bean实例之间有依赖关系时               ,建议使用Full全模式 当在你的同一个Configuration配置类中,注入到容器中的bean实例之间没有依赖关系时                     ,建议使用Lite轻量级模式                      ,以提高springboot的启动速度和性能

proxyBeanMethods 属性默认值是 true, 也就是说该配置类会被代理(CGLIB),在同一个配置文件中调用其它被 @Bean 注解标注的方法获取对象时会直接从 IOC 容器之中获取;

@Bean(value,initMethod,destroyMethod)

标记于方法上              ,将返回值注册进sping                      ,id默认是方法名        ,可以使用value进行更名       。init指定返回值类的初始化方法              ,destroy指定bean销毁方法

@ComponentScan(value[],excludeFilters{},includeFilters{})

\textcolor{#f08080}{标记在类上                     ,开启注解扫描              。excludeFilters和includeFilters根据书写顺序层层过滤}

value 需要扫描的包                      。

excludeFilters={ 指定规则不扫描特定包

@Filter(type=FilterType.ANNOTATION,classes={Controller.class})}

FilterType.Annotation:按照定义的classes规则不扫描指定注解标注的类       。

includeFilters={同上        ,useDefaultFilters=false} 指定规则只扫描特定包

useDefaultFilters=false:将默认的全部扫描规则进行关闭       ,才能达到只扫描指定注解标注类的效果

FilterType.ASPectj: 使用aspectj表达式

FilterType.REgex:使用正则表达式

FilterType.custom:使用自定义规则 自己编写类实现指定接口重写方法

@Controller              、@Component                      、@Service       、@Repository       。

@Scope(value)

\textcolor{#f08080}{标注方法或者类上                     ,设置Bean的作用域}

single:单实例(默认值)ioc容器启动时加载 以后每次获取都是从容器中获取

prototype:多实例 获取Bean时才会创建对象 每次都是新的对象

request:同一次请求创建一个实例

session:同一次会话创建一个实例

@Lazy

\textcolor{#f08080}{懒加载               ,可标注在类       ,方法                     ,全局变量               ,构造函数,形参}

作用:单实例Bean在ioc容器启动时不进行加载                     ,获取Bean时再加载                      ,并且往后每次也是同一个Bean

@Conditional

\textcolor{#f08080}{标记在类和方法上,根据一定条件判断              ,是否将Bean注册进ioc容器 放在类类上将控制整个类的实现                      。}

@Import(values[])

\textcolor{#f08080}{标记在类上                      ,快速给容器导入Bean组件        ,id默认是组件带包全名}

value:类名.class 将类注册进ioc容器 默认id是类全名

实现指定ImportSelector的类名.class:重写方法的返回值(new String[] {“类的全名              ”              ,“全名2                     ”...})一次性导入多个组件

实现ImportBeanDefinitionRegister接口的类名.class:重写方法                     ,调用register.registerBeanDefinition(name        ,new RootBeanDefafinition(类名.class))进行Bean的注册 可以自定义Bean的属性(scope和id)

<u>2       ,3 可以对Bean的注册                     ,进行逻辑判断</u>

FactoryBean< T >接口

工厂bean               ,实现两个方法       ,1:getObject() 将返回值 注册bean进ioc (通过getBean(工厂Bean的id名)获取到的是被该方法注册的Bean 使用$工厂Bean的id名 才能获取到工厂Bean )                      ,2:isSingleton ( return true) true为单实例 默认值

Bean的生命周期

单个Bean实现两个接口

InitializingBean(重写方法 定义初始化逻辑 )早于init-method的执行

DisposableBean接口(重写方法 定义销毁逻辑) 早于destroy-method的执行

单个Bean使用JSR250 的两个注解 (Bean不需要实现接口               ,只能作用于方法上

@PostConstruct 在bean创建完成并属性赋值完成,未初始化间 在initializingBean 前

@PreDestroy 在容器销毁bean之前通知进行清理工作

配置Bean后处理器 类实现BeanPostProcessor 重写两个方法

Bean后处理器将作用于当前配置文件中所有的Bean              。需要加入到容器中@Configuration

postProcessBeforeInitialization 作用于Bean初始化前 (postConstruct前)

postProcessAfterInitialization 作用于Bean初始化后(使用bean前)

需要注意的:

Spring 根据Bean的作用域来选择管理方式       。

对于singleton作用域的Bean                     ,Spring 能够精确地知道该Bean何时被创建                      ,何时初始化完成,以及何时被销毁;

而对于 prototype 作用域的 Bean              ,Spring 只负责创建                      ,(生命周期到7        ,使用)当容器创建了 Bean 的实例后              ,Bean 的实例就交给客户端代码管理                     ,Spring 容器将不再跟踪其生命周期                      。

第一:只有正常关闭spring容器        ,容器.close()       ,bean的销毁方法才会被调用              。

执行顺序:

Bean本身的构造函数

BeanPostProcessor的postProcessBeforeInitialization方法

类中被 @PostConstruct 标注的方法

InitializingBean接口的afterPropertiesSet方法

@Bean()的init-method方法

BeanPostProcessor的postProcessAftrInitialization方法

Bean的使用

类中被 @preDestroy注解标注的方法

Disposable接口的destroy方法

@Bean()的destroy-method方法

使用Bean

@PropertySource(value["classpath:/路径"])

作用在类上                     ,导入外部配置文件 (会将配置文件中的K/v 保存进运行环境变量中 可通过application.environment().getProperty("key")取对应的值)

@Value()

作用在类               ,方法       ,全局属性                     ,方法形参

基本数据类型 string int

可以写spel ; #{20-2}

可以写${}; 搭配@propertySource注解使用(properties,yml)取出配置文件中的值(在运行环境变量中的值)

@Autowired @Qualifier

作用于构造方法上               ,方法上,形参上                     ,属性上                      ,注解上。

该注解有一个required属性,默认值是true              ,表示在注入的时候要求被注入的Bean必须是存在的                      ,如果不存在则报错

如果使用@Autowired进行自动装配的接口有多个实现类        ,会报受检异常                      。此时必须将@Autowired注解和@Qualifier注解联合起来根据名称进行装配              ,在@Qualifier注解中指定Bean名称                      。

@Resource

@Resource注解用在属性上              、setter方法上。

@Resource注解默认根据名称装配byName如果byname为空则根据类型查找

@Profile(value                     ,default)

作用在类和方法上        ,环境标识表示指定组件在哪种(value)环境下才能注册到容器中       ,default设定默认加载

AOP

连接点 Joinpoint

在程序的整个执行流程中                     ,可以织入切面的位置              。方法的执行前后               ,异常抛出之后等位置                      。

切点 Pointcut

在程序执行流程中       ,真正织入切面的方法       。(一个切点对应多个连接点)

通知 Advice

通知又叫增强                     ,就是具体你要织入的代码              。

通知包括:以下的注解都能通过在第一个形参填JoinPoint拿到被增强的方法的信息

@Before("execution")前置通知 目标方法执行之前的通知

@AfterReturning("execution",returnig="方法形参")后置通知 目标方法执行之后的通知 可在通知中获取到返回值

@Around("execution")环绕通知

@AfterThrowing("execution",throwing="形参")异常通知 发生异常之后执行的通知 可在通知中获取到抛出的异常

@After("execution")最终通知 放在finally语句块中的通知

下面是执行顺序 注意:出现异常之后               ,后置通知环绕通知的结束部分不会执行                      。

切面 Aspect

切点 + 通知就是切面       。

织入 Weaving

把通知应用到目标对象上的过程       。

代理对象 Proxy

一个目标对象被织入通知后产生的新对象                      。

目标对象 Target

被织入通知的对象              。

切入点表达式 execution

execution( [访问控制权限修饰符] 返回值类型 [全限定类名]方法名(形式参数列表) [异常])

[ ]中的内容是可选项,其余必填

service包下所有的类中以delete开始的所有方法execution(public * com.powernode.mall.service.*.delete*(..)) mall包下所有的类的所有的方法 两个点“..        ”代表当前包以及子包下的所有类       。execution(* com.powernode.mall..*(..))

@Pointcut(execution)

作用于方法上                     ,抽取公共的切入点表达式                      ,本类中直接引用方法名,其他类中引用需要填带包全类名

@Pointcut("execution(* com.powernode.spring6.service.OrderService.*(..))") public void pointcut(){}----------------本类中以方法名引用------------------------------------@Around("()") public void aroundAdvice(){ System.out.println("环绕通知开始");}----------------其他类中引用需要填带包全类名----------------------------​@Around("com.powernode.mall.类名.pointcut()") public void aroundAdvice(){ System.out.println("环绕通知开始");}

基于AspectJ的AOP注解式开发

第一步:定义目标类以及目标方法(记得添加core              ,aspectj                      ,aop依赖)

第二步:定义切面类 切面类加注解@Aspect 告诉ioc这是切面类

第三步:目标类和切面类都纳入spring bean管理 使用@Configuration + @Bean

第四步:在spring配置类上添加 @Enable Aspect JAutoProxy 开启基于注解的aop功能

第五步:在切面类中添加通知

第六步:在通知上添加切点表达式

@EnableAspectJAutoProxy(proxyTargetClass = true)

作用在类上        ,表示开启开启基于注解的aop功能

proxy-target-class="true" 表示采用cglib动态代理                      。 底层采用继承的方式实现              。所以被代理的目标类不能使用final修饰。 需要引入它的依赖: 它既可以代理接口              ,又可以代理类

proxy-target-class="false" 表示采用jdk动态代理                      。默认值是false                      。即使写成false                     ,当没有接口的时候        ,也会自动选择cglib生成代理类。 只能代理接口              。

@Order(int)

可标注在方法       ,类                     ,属性上               ,用于提高优先级       ,数字越小优先级越高

例如:可以使用@Order注解来标识切面类                     ,为@Order注解的value指定一个整数型的数字               ,数字越小,优先级越高                      。

事务

什么是事务

在一个业务流程当中                     ,通常需要多条DML(insert delete update)语句共同联合才能完成                      ,这多条DML语句必须同时成功,或者同时失败              ,这样才能保证数据的安全       。

多条DML要么同时成功                      ,要么同时失败        ,这叫做事务              。

事务:Transaction(tx)

事务的四个处理过程:

第一步:开启事务 (start transaction)

第二步:执行核心业务代码

第三步:提交事务(如果核心业务处理过程中没有出现异常)(commit transaction)

第四步:回滚事务(如果核心业务处理过程中出现异常)(rollback transaction)

事务的四个特性:

A 原子性:事务是最小的工作单元              ,不可再分                      。

C 一致性:事务要求要么同时成功                     ,要么同时失败       。事务前和事务后的总量不变       。

I 隔离性:事务和事务之间因为有隔离性        ,才可以保证互不干扰                      。

D 持久性:持久性是事务结束的标志              。

事务属性

事务中的重点属性:

事务传播行为

什么是事务的传播行为?

在service类中有a()方法和b()方法       ,a()方法上有事务                     ,b()方法上也有事务               ,当a()方法执行过程中调用了b()方法       ,事务是如何传递的?合并到一个事务里?还是开启一个新的事务?这就是事务传播行为       。

事务隔离级别

事务超时

只读事务

设置出现哪些异常回滚事务

设置出现哪些异常不回滚事务

一共有七种传播行为:

REQUIRED:支持当前事务                     ,如果不存在就新建一个(默认)【没有就新建               ,有就加入】

SUPPORTS:支持当前事务,如果当前没有事务                     ,就以非事务方式执行【有就加入                      ,没有就不管了】

MANDATORY:必须运行在一个事务中,如果当前没有事务正在发生              ,将抛出一个异常【有就加入                      ,没有就抛异常】

REQUIRES_NEW:开启一个新的事务        ,如果一个事务已经存在              ,则将这个存在的事务挂起【不管有没有                     ,直接开启一个新事务        ,开启的新事务和之前的事务不存在嵌套关系       ,之前事务被挂起】

NOT_SUPPORTED:以非事务方式运行                     ,如果有事务存在               ,挂起当前事务【不支持事务       ,存在就挂起】

NEVER:以非事务方式运行                     ,如果有事务存在               ,抛出异常【不支持事务,存在就抛异常】

NESTED:如果当前正有一个事务在进行中                     ,则该方法应当运行在一个嵌套式事务中                      。被嵌套的事务可以独立于外层事务进行提交或回滚              。如果外层事务不存在                      ,行为就像REQUIRED一样。【有事务的话,就在这个事务里再嵌套一个完全独立的事务              ,嵌套的事务可以独立的提交和回滚                      。没有事务就和**REQUIRED一样                      。】**

@Transactional(propagation = Propagation.REQUIRED) 在代码中设置事务的传播行为:@Transactional(propagation = Propagation.REQUIRED)

注解实现事务

@EnableTransactionManagement

第一步:在spring配置文件中开启基于注解的事务管理功能。@Configration

第二步:导入依赖                      ,通过@Bean配置数据源        ,注册事务管理器进容器中

@Transactional

第三步:给方法上添加@Transactional 表示当前方法开启事务管理

事务的隔离级别

事务隔离级别类似于教室A和教室B之间的那道墙              ,隔离级别越高表示墙体越厚              。隔音效果越好                      。

数据库中读取数据存在的三大问题:(三大读问题)

脏读:读取到没有提交到数据库的数据                     ,叫做脏读       。

不可重复读:在同一个事务当中        ,第一次和第二次读取的数据不一样              。

幻读:读到的数据是假的                      。

事务隔离级别包括四个级别:

读未提交:READ_UNCOMMITTED

这种隔离级别       ,存在脏读问题                     ,所谓的脏读(dirty read)表示能够读取到其它事务未提交的数据       。

读提交:READ_COMMITTED

解决了脏读问题               ,其它事务提交之后才能读到       ,但存在不可重复读问题       。

可重复读:REPEATABLE_READ

解决了不可重复读                     ,可以达到可重复读效果               ,只要当前事务不结束,读取到的数据一直都是一样的                      。但存在幻读问题              。

序列化:SERIALIZABLE

解决了幻读问题                     ,事务排队执行       。不支持并发                      。

大家可以通过一个表格来记忆:

大家可以通过一个表格来记忆:

隔离级别 脏读 不可重复读 幻读 读未提交 读提交 可重复读 序列化

在Spring代码中如何设置隔离级别?

隔离级别在spring中以枚举类型存在:

@Transactional(isolation = Isolation.READ_COMMITTED) @Transactional(isolation = Isolation.READ_COMMITTED)

事务超时

@Transactional(timeout = 10)

以上代码表示设置事务的超时时间为10秒              。

表示超过10秒如果该事务中所有的DML语句还没有执行完毕的话                      ,最终结果会选择回滚。

默认值-1,表示没有时间限制                      。

这里有个坑              ,事务的超时时间指的是哪段时间?

在当前事务当中                      ,最后一条DML语句执行之前的时间                      。如果最后一条DML语句后面很有很多业务逻辑        ,这些业务代码执行的时间不被计入超时时间。

当然              ,如果想让整个方法的所有代码都计入超时时间的话                     ,可以在方法最后一行添加一行无关紧要的DML语句              。

只读事务

@Transactional(readOnly = true)

将当前事务设置为只读事务        ,在该事务执行过程中只允许select语句执行       ,delete insert update均不可执行                      。

该特性的作用是:启动spring的优化策略       。提高select语句执行效率              。

如果该事务中确实没有增删改操作                     ,建议设置为只读事务                      。

@Transactional(rollbackFor = RuntimeException.class)

设置哪些异常回滚事务:表示只有发生RuntimeException异常或该异常的子类异常才回滚

@Transactional(noRollbackFor = NullPointerException.class)

设置哪些异常不回滚事务: 表示发生NullPointerException或该异常的子类异常不回滚               ,其他异常则回滚       。

@WebMvc

作用在类上       ,结合类实现HttpServlet                     ,作用:代替xml配置方式       。 同理@WebFIlter               ,@WebListener都是

@EnableWebMvc

作用在类上,代替xml定制mvc                      。标记的类实现WebMvcConfigurerAdapter抽象类                     ,通过实现其方法进行                      ,开启静态资源放行,设置视图解析器              ,配置拦截器等              。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
全自动怎么接龙头(全自动内链插件——让WordPress更智能)