spring5学习笔记其一

蔚落 2023-10-14 15:26 112阅读 0赞

1.bean对象成员属性赋值

注入bean对象时,需要写出类的set方法,底层也是基于这个set函数来给类的成员属性赋值的。


2.有其它类作为该类的成员属性

通过xml形式来配置bean对象时,当一个类中,有其他类的对象做成员属性时,可以使用ref外部bean对象或者property注入内部对象的方式来描述。


3.注入属性注意事项

当通过

  1. <property name="address" value="贵州省安顺市"/>

这样注入属性值时,需要在类中写出对应属性的set方法,不然会出错。


4.级联赋值

  1. <bean id="empEntity" class="com.lzx.entity.EmpEntity">
  2. <property name="name" value="lzx"/>
  3. <property name="address" value="贵州省安顺市"/>
  4. <property name="deptEntity" ref="deptEntity"/>
  5. <property name="deptEntity.name" value="IT部门"/>
  6. </bean>
  7. <bean id="deptEntity" class="com.lzx.entity.DeptEntity"/>

级联赋值注入集合:

  1. <bean id="stuEntity" class="com.lzx.entity.StuEntity">
  2. <property name="list">
  3. <list>
  4. <value>lzx</value>
  5. <value>yy</value>
  6. </list>
  7. </property>
  8. <property name="arrays">
  9. <array>
  10. <value>我爱你</value>
  11. <value>非常爱你</value>
  12. </array>
  13. </property>
  14. <property name="map">
  15. <map>
  16. <entry key="67" value="a"></entry>
  17. </map>
  18. </property>
  19. <property name="set">
  20. <set>
  21. <value>666</value>
  22. <value>777</value>
  23. <value>666</value>
  24. </set>
  25. </property>
  26. </bean>

注入的list类型为对象的:

在StuEntity中有List courses;

  1. <property name="courses">
  2. <list>
  3. <ref bean="courseEntity"/>
  4. </list>
  5. </property>
  6. <bean id="courseEntity" class="com.lzx.entity.CourseEntity">
  7. <property name="name" value="Java"/>
  8. </bean>

5. 在spring的配置文件中对集合统一配置

对list提取出公共配置,在spring的配置文件中,若该对象有多个list属性,并且list的值有公共部分,注入属性值比较麻烦,可提取出来。

需要对sping.xml文件修改一下头部(目的是使用util标签):

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:util="http://www.springframework.org/schema/util"
  5. xsi:schemaLocation="http://www.springframework.org/schema/beans
  6. http://www.springframework.org/schema/beans/spring-beans.xsd
  7. http://www.springframework.org/schema/util
  8. http://www.springframework.org/schema/util/spring-util.xsd">
  9. <util:list id="list">
  10. <value>lzx</value>
  11. <value>yy</value>
  12. </util:list>
  13. <!-- 配置注入spring bean对象
  14. id命名一般为类名的首字母小写
  15. class
  16. -->
  17. <bean id="stuEntity" class="com.lzx.entity.StuEntity">
  18. <property name="list" ref="list"/>
  19. </bean>
  20. </beans>

6. IOC操作bean管理

65f417919bd64c74ab5ffbf43e972586.png

  1. package com.lzx.factorybean;
  2. import org.springframework.beans.factory.FactoryBean;
  3. public class MyFactoryBean implements FactoryBean {
  4. @Override
  5. public Object getObject() throws Exception {
  6. return new Object();
  7. }
  8. @Override
  9. public Class<?> getObjectType() {
  10. return null;
  11. }
  12. }

底层是在类中自己实现需要返回哪个类。在spring的bean配置文件中也需要正常配置该实现了FactoryBean类的类


7.spring中bean的作用域

单例配置:

  1. <bean id="userEntity" class="com.mayikt.entity.UserEntity" scope="singleton"></bean>

多例配置:

  1. <bean id="userEntity" class="com.mayikt.entity.UserEntity" scope="prototype"></bean>

默认为单例。


8. springbean的生命周期

对象的创建与销毁的过程,类似之前学习servlet生命的周期过程。

生命周期的原理:

  1. 通过构造函数创建bean对象(默认执行无参构造函数 底层基于反射实现)
  2. 为bean的属性设置 (使用反射调用set方法)
  3. 调用bean的初始化的方法(需要单独在类中配置初始化的方法)
  4. 正常使用bean对象
  5. Spring容器关闭,调用该类的销毁回调的方法(需要单独在类中配置销毁的方法)

还需要在spring的bean配置文件中写上:

  1. <bean id="memberEntity" class="com.mayikt.entity.MemberEntity" init-method="initMethod" destroy-method="destroyMethod">
  2. <property name="name" value="mayikt"></property>
  3. </bean>
  4. <bean id="mayiktBeanPost" class="com.mayikt.bean.MayiktBeanPost"></bean>

9.springbean的生命周期核心

springbean的生命周期核心—-后置处理器(BeanPostProcessor):

在init方法之前和之后执行。通过实现BeanPostProcessor接口,重写两个方法。

在springbean配置文件中定义了后置处理器的bean后,那么该配置文件的所有bean都是需要走该后置处理器。配置后置处理器和配置常规类是一样的。

一个bean对象可以走多个后置处理器,当有多个后置处理器时,可以在后置处理器中实现Ordered接口,再重写getOrder方法,返回值越小越先执行。


10spring自动装配bean

在xml文件配置中,autowire属性配置,有两个值,byName是在类中的属性名称匹配xml文件中的其它bean,若相同则自动赋值。byType就是看其它bean的class类型与成员属性的类型有没有相同的,有就自动赋值。


11. Java反射技术

cb079ff07e7d4866ae3a9a4f504515d3.png

dcbfcb039f3649268e1456ec6bd8f78c.png

class.forName()初始化对象。在需要使用该对象时,才会使用类加载器的方法来加载.class文件到内存中。

三种获取类的方式:

01bf69b580e84cefa4e2d78be5e0859e.png

还可以通过获取到的该类,来调用到类中的所有方法,包括私有、公有,也可以为变量设置值,也是包括私有和公有。


12.spring中的AOP技术

基于代理设计模式封装。

代理设计模式又分为静态代理和动态代理。

动态代理又分为jdk动态代理和cglib动态代理。

将重复的代码单独放到一个类中,再在这个类中调用其它类的目标方法。

比如在目标方法前后开启事务、在目标方法前后输出日志。

静态代理设计模式的实现(使用于类少):

一个接口、该接口的实现类、代理类,客户端。四个文件实现。

可以通过实现接口的方式实现、可以通过继承接口的实现类来实现(该方法用得很少,Java不支持多继承)。

更多使用JDK动态代理或者cglib代理:

9d6f98a6c7bd427da55e0ddb1a6e0f45.png

使用JDK动态代理来实现Mybatis中的mapper。

cglib动态代理:

1da8fe7f694d4950adb220aeeef924e4.png

代理类直接继承接口的实现类


13. AOP详解

AOP, 或者面向切面编程(Aspect-Oriented Programming),是一种软件开发的编程思想和方法论。它的目标是将横切关注点(如日志记录、事务管理、安全性等)与核心业务逻辑相分离,从而提高代码的可维护性和重用性。

在AOP中,横切关注点被称为切面(Aspect),切面通过定义一些特定的通知(Advice),在程序的不同位置被织入到被称为连接点(Join Point)的代码位置上。通知可以在连接点之前、之后或者环绕连接点执行。

AOP的一个重要概念是切点(Pointcut),切点用于定义在哪些连接点上应该执行特定的通知。切点使用一种特定的表达式语言来描述连接点的选择。

AOP提供了一种更加灵活的编程方式,可以在不修改核心业务逻辑的情况下,很方便地添加和管理横切关注点。它广泛应用于日志记录、事务管理、权限控制等领域。

总结来说,AOP是一种面向切面的编程思想,通过将横切关注点与核心业务逻辑分离,提高了代码的可维护性和重用性。

前置通知、后置通知、异常通知、环绕通知。

@AfterReturning 表达后置通知注解。在目标方法返回结果后执行。

异常通知:目标方法抛出异常后才会通知。

  1. package com.lzx.proxy;
  2. import org.aspectj.lang.ProceedingJoinPoint;
  3. import org.aspectj.lang.annotation.*;
  4. import org.springframework.stereotype.Component;
  5. /**
  6. * @author 梁志雄
  7. * @date 2023/8/9 15:51
  8. */
  9. @Component //加上该注解,相当于在xml文件中配置了bean,自动加入spring的IOC容器中。
  10. @Aspect //定义切面
  11. public class UserProxy {
  12. //前置通知、后置通知、环绕通知、异常通知
  13. //@Before(value = "execution(* com.lzx.service.LzxService.*(..))") //定义切入点
  14. //public void beforeNotification(){
  15. // System.out.println("在目标方法之前执行...");
  16. //}
  17. //
  18. //@After(value = "execution(* com.lzx.service.LzxService.*(..))")
  19. //public void afterNotification(){
  20. // System.out.println("在目标方法之后执行...");
  21. //}
  22. @Around(value = "execution(* com.lzx.service.LzxService.*(..))")
  23. //环绕通知可以获取到当前目标的信息
  24. public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
  25. System.out.println("环绕通知前...");
  26. Object result = proceedingJoinPoint.proceed(); //调用目标方法的返回结果(也即目标方法的返回结果)
  27. System.out.println("环绕通知后...");
  28. System.out.println(result+"环绕通知");
  29. }
  30. @AfterThrowing(value = "execution(* com.lzx.service.LzxService.*(..))")
  31. public void afterThrowing(){
  32. System.out.println("异常通知,在方法抛出异常时执行。");
  33. }
  34. }

spring的AOP底层基于代理模式封装。使用的cglib

如果被代理类有接口,那么就是使用的JDK动态代理。

如果没有,默认走cglib动态代理。

在前置通知中,可使用API来获取到目标方法传入的参数:

  1. @Before(value = "execution(* com.lzx.service.LzxService.*(..))") //定义切入点
  2. public void beforeNotification(JoinPoint joinPoint){
  3. Object[] args = joinPoint.getArgs();
  4. System.out.println(Arrays.toString(args));
  5. System.out.println("在目标方法之前执行...");
  6. }

@PointCut注解定义切入点。

发表评论

表情:
评论列表 (有 0 条评论,112人围观)

还没有评论,来说两句吧...

相关阅读

    相关 spring5学习笔记其一

    1.bean对象成员属性赋值 注入bean对象时,需要写出类的set方法,底层也是基于这个set函数来给类的成员属性赋值的。 --------------------