Spring5学习小总结

阅读: 评论:0

Spring5学习小总结

Spring5学习小总结

本文根据尚硅谷王老师的Spring5视频教程总结的。z作者跟着教程全程实践,本文内容较为简略,详细内容请移步王老师视频教程。

目录

    • 一、概述
    • 二、IOC
      • 1、IOC底层原理
      • 2、IOC接口(BeanFactory)
      • 3、IOC操作Bean管理
        • 基于xml方式
        • 基于注解方式
        • 完全注解开发
        • FactoryBean
        • bean作用域
        • 外部属性文件
    • 三、AOP
      • 1、AOP底层原理
        • JDK动态代理
      • 2、AOP术语
      • 3、AOP操作(准备工作)
      • 4、AOP操作(AspectJ注解)
    • 四、JdbcTemplate
      • 准备工作
      • 操作数据库
    • 五、事务管理
      • Spring声明式事务管理(注解)
      • 完全注解开发
    • 六、Spring5新特性
      • 1、日志封装
      • 2、@Nullable 注解
      • 3、JUnit5
      • 4、Webflux

一、概述

轻量级开源的JavaEE框架

核心部分:

​ (1)IOC:控制反转,将创建对象交给Spring管理

​ (2)AOP:面向切面,不修改源代码进行功能增强

IOC基本包:

二、IOC

控制反转:将创建对象和对象之间的调用过程交给Spring进行管理

使用目的:降低代码耦合度

1、IOC底层原理

xml解析、工厂模式、反射

第一步:xml配置文件,配置创建的对象(bean对象)

第二步:创建工厂类

2、IOC接口(BeanFactory)

IOC基于IOC容器完成,IOC容器底层即对象工厂

IOC容器实现:

​ (1)BeanFactory:加载配置文件时不会创建对象,在获取对象(使用)时才会去创建对象 (内部使用接口)

​ (2)ApplicationContext:加载配置文件时就会把配置文件中的对象创建 (开发人员使用)

3、IOC操作Bean管理

Bean管理:

​ (1)创建对象

​ (2)注入属性

基于xml方式

创建对象:

​ 在配置文件中添加bean标签,标签中添加对应属性,实现对象创建

注入属性:

​ (1)使用set方法注入

​ 类中创建对应属性set()方法—>配置文件中配置属性注入

/*** 演示使用set方法注入属性*/
public class Book {//创建属性private String bname;private String bauthor;private String adderss;//创建属性对应的set方法public void setBname(String bname){this.bname = bname;}public void setBauthor(String bauthor) {this.bauthor = bauthor;}public void setAddress(String address) {this.adderss = address;}public void testDemo(){System.out.println(bname+" "+bauthor+" "+adderss);}
}<!-- 2 set方法注入属性-->
<bean id="book" class="com.atguigu.spring5.Book"><!-- 使用property完成属性注入 --><property name="bname" value="易筋经"></property><property name="bauthor" value="达摩老祖"/><!-- 属性值为空 --><!--<property name="address"><null></null></property>--><!-- 属性值包含特殊字符 --><property name="address"><value><![CDATA[<<南京>>]]></value></property>
</bean>

​ (2)使用有参构造函数注入

​ 类中创建对应属性有参构造方法—>配置文件中属性注入

public class Orders {//属性private String oname;private String address;//有参构造public Orders(String oname, String address) {ame = oname;this.address = address;}public void testOrders(){System.out.println(oname+" "+address);}
}<!-- 3 有参构造注入属性 -->
<bean id="orders" class="com.atguigu.spring5.Orders"><constructor-arg name="oname" value="abc"></constructor-arg><constructor-arg name="address" value="Chain"></constructor-arg>
</bean>

注入外部属性(默认set()方法注入)

​ 类中属性为另一个类(如service中注入dao)

​ 创建两个类service和dao—>seivice中属性为dao—>为dao创建set()方法—>配置类中创建service和dao对象—>在service的bean对象中注入dao对象

public class UserService {//创建UserDao类型属性,生成set方法private UserDao userDao;public void setUserDao(UserDao userDao){this.userDao = userDao;}public void add(){System.out.println("");userDao.update();//原始方式//UserDao userDao = new UserDaoImpl();//userDao.update();}
}<!-- 1 service和dao对象创建 -->
<bean id="userService" class="com.atguigu.spring5.service.UserService"><!--2 注入UserDao对象name属性:类里面属性名称ref属性:创建userDao对象bean标签id值--><property name="userDao" ref="userDaoImpl"></property>
</bean>
<bean id="userDaoImpl" class="com.atguigu.spring5.dao.UserDaoImpl"></bean>

注入内部属性(默认set()方法注入)

<!-- 内部bean -->
<bean id="emp" class="com.atguigu.spring5.bean.Emp"><!-- 先设置两个普通的属性 --><property name="ename" value="lucy"></property><property name="gender" value="女"></property><!-- 设置对象类型属性 --><property name="dept"><bean id="dept" class="com.atguigu.spring5.bean.Dept"><property name="dname" value="安保部"></property></bean></property>
</bean>

注入集合属性(默认set()方法注入)

​ 创建类,定义数组、list、map、set类型属性,生成set()方法—>在配置文件中进行配置

<!-- 集合类型属性注入 -->
<bean id="stu" class="com.atgui<!-- 数组类型属性注入 --><property name="course"><array><value>java课程</valu<value>数据库课程</value</array></property><!-- list类型属性注入 --><property name="list"><list><value>张三</value><value>小三</value></list></property><!-- map类型属性注入 --><property name="maps"><map><entry key="JAVA" v<entry key="PHP" va</map></property><!-- set类型属性注入 --><property name="set"><set><value>MySQL</value<value>Redis</value</set></property><!-- 注入List集合类型,值是对象 --><property name="courseList"<list><ref bean="course1"<ref bean="course2"</list></property>
</bean><!-- 创建多个course对象 -->
<bean id="course1" class="com.llectiontype.Course"><property name="cname" value="Spring5框架"></property>
</bean>
<bean id="course2" class="com.llectiontype.Course"><property name="cname" value="MyBatis框架"></property>
</bean>
基于注解方式

注解格式:@注解名称(属性名称=属性值,属性名称=属性值…)

使用目的:简化xml配置

Bean管理注解:@Controller、@Service、@Repository、@Component

创建对象:

​ 引入依赖—>开启组件扫描—>在类上面添加注解—>组件扫描细节

<!-- 开启组件扫描 1 如果扫描多个包,使用逗号隔开2 扫描包上层目录-->
<context:component-scan base-package="com.atguigu.spring5.aopanno"></context:component-scan>
//在注解里面value可以省略不写,默认是类名称首字母小写   UserService->userService
//@Component(value = "userService")   //类似于xml文件中定义<bean id="userService" class=".."/>
@Service
//@Controller
//@Repository
public class UserService {}

属性注入:

​ @Autowired:根据属性类型进行自动装配

​ @Qualifier:根据名称进行注入

​ @Resource:根据属性类型或者名称进行注入

​ @Value:注入普通类型属性

​ 创建service和dao对象—>在service和dao上添加注解—>开启组件扫描

​ 在service中添加dao属性—>在属性上使用注入注解

完全注解开发

​ 创建配置类代替xml配置文件

@Configuration  //作为配置类,替代xml配置文件
@ComponentScan(basePackages = {"com.atguigu"})
public class SpringConfig { }
FactoryBean

​ 普通bean:配置文件中定义的bean类型就是返回类型

​ 工厂Bean:配置文件中定义的bean类型和返回类型不一样

​ (1)创建类,让其作为工厂类,实现接口FactoryBean

​ (2)实现接口里面的方法,在实现的方法中定义返回的bean类型

bean作用域

​ 默认情况下,bean是单实例对象—意思是创建的多个实例对象,其指向的地址是一个

​ 设置多实例对象—只需在配置文件bean标签中设置scope属性为prototype

​ 区别:

​ 单实例在加载配置文件时就会创建单实例对象

​ 多实例在调用getBean方法是创建多实例对象

外部属性文件

​ (1)配置数据库信息

​ 配置德鲁伊连接池—>引入德鲁伊的依赖jar包

<!-- 数据库连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close"><property name="url" value="jdbc:mysql://localhost:3306/userDb" /><property name="driverClassName" value=&#sql.jdbc.Driver" /><property name="username" value="root" /><property name="password" value="123" />
</bean>

​ (2)引入外部properties属性文件到配置文件中

​ 引入conetxt名称空间—>配置文件中使用标签引入外部属性文件

<!-- 引入外部属性文件  -->
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
<!-- 配置连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${prop.driverClass}"></property><property name="url" value="${prop.url}"></property><property name="username" value="${prop.username}"></property><property name="password" value="${prop.password}"></property>
</bean>

三、AOP

面向切面编程,可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低。即:通过不修改源代码的方式,在主干功能里边添加新功能

1、AOP底层原理

使用动态代理

(1)有接口,使用JDK动态代理

创建接口实现类代理对象,增强类的方法

(2)无接口,使用CGLIB动态代理

创建当前类子类的代理对象,增强类的方法

JDK动态代理

(1)使用Proxy类中的方法创建代理对象

方法中的三个参数分别是类加载器、增强方法所在的类、实现这个接口的InvocationHandler

(2)编写JDK动态代理代码

创建接口,定义方法—>创建接口实现类,实现方法—>使用Proxy类创建接口代理对象—>创建代理对象代码

 // 创建接口实现类代理对象         
public class JDKProxy {     public static void main(String[] args) { Class[] interfaces = {UserDao.class}; UserDaoImpl userDao = new UserDaoImpl();         UserDao dao = (UserDao)Proxy. newProxyInstance (ClassLoader(), interfaces, new UserDaoProxy(userDao)); int result = dao.add(1, 2);System. out .println("result:"+result); }
}
// 创建代理对象代码 
class UserDaoProxy implements InvocationHandler {     //1 把创建的是谁的代理对象,把谁传递过来     // 有参数构造传递     private Object obj;     public UserDaoProxy(Object obj) {         this.obj = obj;     }     // 增强的逻辑     @Override     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {         // 方法之前         System. out .println("方法之前执行...."&#Name()+" :传递的参 数..."+ Arrays. toString (args));         // 被增强的方法执行         Object res = method.invoke(obj, args);         // 方法之后         System. out .println("方法之后执行...."+obj);         return res;     } 
}

2、AOP术语

连接点:类里面哪些方法可以被增强,这些方法称为连接点

切入点:实际被增强的方法

通知(增强):实际增强的逻辑部分 (分类为前置、后置、环绕、异常、最终通知)

切面:把通知应用到切入点的过程

3、AOP操作(准备工作)

一般地,通过AspectJ和Spring框架一起使用进行AOP操作

基于AspectJ实现方式:xml和注解

引入AOP相关依赖

切入点表达式:知道对哪个类的哪个方法进行增强: execution(* [返回类型] [类全路径] 方法名称 ) :例:execution(* com.atguigu.dao.BookDao.add(…))

4、AOP操作(AspectJ注解)

—>创建类,在类里面定义方法

—>创建增强类(编写增强逻辑)

—>进行通知的配置

​ 开启注解扫描->@Component注解上面创建的类->在增强类上添加注解@Aspect->开启Aspect生成代理对象

<!-- 开启 Aspect 生成代理对象 --> 
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

—>配置不同类型的通知

​ 在增强类的里面,在作为通知方法上面添加通知类型注解,使用切入点表达式配置

@Before(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))") 

—>相同的切入点的抽取

@Pointcut(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))") 

—>有多个增强类对同一方法进行增强,设置增强类优先级

​ 增强类上面添加注解 @Order(数字类型值),数字类型值越小优先级越高

—>完全使用注解开发

@Configuration 
@ComponentScan(basePackages = {"com.atguigu"}) @EnableAspectJAutoProxy(proxyTargetClass = true) 
public class ConfigAop { }

四、JdbcTemplate

Spring框架对JDBC进行封装,使用JdbcTemplate实现对数据库的操作

准备工作

—>引入相关jar包

—>配置文件中配置组件扫描和数据库连接池dataSource

—>配置JdbcTemplate对象,注入dataSource

—>创建service类和dao类,在dao中注入jdbcTemplate对象

操作数据库

//添加数据
//1 创建 sql 语句         
String sql = "insert into t_book values(?,?,?)";         
//2 调用方法实现         
Object[] args = {UserId(), Username(), Ustatus()};         
int update = jdbcTemplate.update(sql,args); //修改数据
String sql = "update t_book set username=?,ustatus=? where user_id=?";     
Object[] args = {Username(), Ustatus(),UserId()};     
int update = jdbcTemplate.update(sql, args); //删除数据String sql = "delete from t_book where user_id=?";     
int update = jdbcTemplate.update(sql, id); //查询表记录
String sql = "select count ( * ) from t_book";     
Integer count = jdbcTemplate.queryForObject(sql, Integer.class);//查询返回对象
String sql = "select * from t_book where user_id=?";     
Book book = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Book>(Book.class), id); //查询返回集合
String sql = "select * from t_book";
List<Book> bookList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Book>(Book.class));//批量添加
public void batchAddBook(List<Object[]> batchArgs) {     String sql = "insert into t_book values(?,?,?)";     int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);System.out.String(ints)); 
}
//批量添加测试
List<Object[]> batchArgs = new ArrayList<>(); 
Object[] o1 = {"3","java","a"}; 
Object[] o2 = {"4","c++","b"}; 
Object[] o3 = {"5","MySQL","c"}; 
batchArgs.add(o1); batchArgs.add(o2); batchArgs.add(o3); 
bookService.batchAdd(batchArgs); //批量修改
public void batchUpdateBook(List<Object[]> batchArgs) {     String sql = "update t_book set username=?,ustatus=? where user_id=?";     int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);     System. out .println(Arrays. toString (ints)); 
} 
List<Object[]> batchArgs = new ArrayList<>(); 
Object[] o1 = {"java0909","a3","3"}; 
Object[] o2 = {"c++1010","b4","4"}; 
Object[] o3 = {"MySQL1111","c5","5"}; 
batchArgs.add(o1); batchArgs.add(o2); batchArgs.add(o3); 
bookService.batchUpdate(batchArgs);//批量删除
public void batchDeleteBook(List<Object[]> batchArgs) {    String sql = "delete from t_book where user_id=?";     int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);     System. out .println(Arrays. toString (ints)); 
} 
List<Object[]> batchArgs = new ArrayList<>(); 
Object[] o1 = {"3"}; Object[] o2 = {"4"}; 
batchArgs.add(o1); batchArgs.add(o2); 
bookService.batchDelete(batchArgs);

五、事务管理

事务是数据库操作最基本单元,逻辑上一组操作,要么都成功,如果有一个失败所有操作都失败

特性(ACID):原子性、一致性、隔离性、持久性

Spring声明式事务管理(注解)

—>配置文件中配置事务管理器并引入名称空间tx

<! -- 创建事务管理器 -- > 
<bean id="transactionManager"                        class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property> 
</bean>

—>开启事务注解

<! -- 开启事务注解 -- > 
<tx:annotation-driven transactionmanager="transactionManager"></tx:annotation-driven> 

—>在所需的类或方法上添加事务注解@Transactional

—>事务管理参数配置

​ propagation:事务传播行为

​ ioslation:事务隔离级别,多事务操作之间不会产生影响,解决:脏读、不可重复读、虚(幻)读

​ timeout:超时时间

​ readOnly:是否只读

​ rollbackFor:回滚

​ noRollbackFor:不回滚

完全注解开发

@Configuration // 配置类 
@ComponentScan(basePackages = "com.atguigu") // 组件扫描 
@EnableTransactionManagement // 开启事务 
public class TxConfig {     // 创建数据库连接池    @Bean     public DruidDataSource getDruidDataSource() {         DruidDataSource dataSource = new DruidDataSource();dataSource.setDriverClassName(&#sql.jdbc.Driver");dataSource.setUrl("jdbc:mysql:///user_db");         dataSource.setUsername("root");         dataSource.setPassword("root");         return dataSource;     }     // 创建 JdbcTemplate 对象     @Bean     public JdbcTemplate getJdbcTemplate(DataSource dataSource) {         // 到 ioc 容器中根据类型找到 dataSource         JdbcTemplate jdbcTemplate = new JdbcTemplate();         // 注入 dataSource         jdbcTemplate.setDataSource(dataSource); return jdbcTemplate;     }    // 创建事务管理器     @Bean     public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource) {DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();transactionManager.setDataSource(dataSource);         return transactionManager;     } 
}

六、Spring5新特性

1、日志封装

引入jar包—>创建 l配置文件

<? xml version="1.0" encoding="UTF-8" ?> 
<! -- 日志级别以及优先级排序 : OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -- > 
<! -- Configuration 后面的 status 用于设置 log4j2 自身内部的信息输出,可以不设置, 当设置成 trace 时,可以看到 log4j2 内部各种详细输出 -- > 
<configuration status="INFO">     <! -- 先定义所有的 appender -- >     <appenders>         <! -- 输出日志信息到控制台 -- >         <console name="Console" target="SYSTEM_OUT">             <! -- 控制日志输出的格式 -- >             <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %5level %logger{36} - %msg%n"/>         </console>     </appenders>     <! -- 然后定义 logger ,只有定义 logger 并引入的 appender , appender 才会生效 -- >     <! -- root :用于指定项目的根日志,如果没有单独指定 Logger ,则会使用 root 作为 默认的日志输出 -- > <loggers>         <root level="info">             <appender-ref ref="Console"/>         </root></loggers>
</configuration>

2、@Nullable 注解

@Nullable 注解可以使用在方法上面,属性上面,参数上面,表示方法返回可以为空,属性值可以为空,参数值可以为空

3、JUnit5

引入测试依赖jar包—>使用注解创建测试类

@RunWith(SpringJUnit4ClassRunner.class) // 单元测试框架
@ContextConfiguration("l") // 加载配置文件
//使用一个复合注解替代上面两个注解
//@SpringJUnitConfig(locations = "l") 	
public class JTest4 {@Autowiredprivate UserService userService;@Testpublic void test1() {userService.accountMoney();}
}

以上是JUnit4,使用JUnit5只需在导入@Test换成5的即可

4、Webflux

Spring5 添加新的模块,用于 web 开发的,功能和 SpringMVC 类似的,Webflux 使用 当前一种比较流程响应式编程出现的框架

使用传统 web 框架,比如 SpringMVC,这些基于 Servlet 容器,Webflux 是一种异步非阻 塞的框架,异步非阻塞的框架在 Servlet3.1 以后才支持,核心是基于 Reactor 的相关 API 实现的

异步和同步针对调用者,调用者发送请求,如果等着对方回应之后才去做其他事情就是同 步,如果发送请求之后不等着对方回应就去做其他事情就是异步

阻塞和非阻塞针对被调用者,被调用者受到请求之后,做完请求任务之后才给出反馈就是阻 塞,受到请求之后马上给出反馈然后再去做事情就是非阻塞

实例:

第一步 创建 SpringBoot 工程,引入 Webflux 依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

第二步 配置启动端口号

server.port=8081

第三步 创建包和相关类

//实体类
public class User {private String name;private String gender;private Integer age;public User(String name, String gender, Integer age) {this.name = der = gender;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getGender() {return gender;}public void setGender(String gender) {der = gender;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}
}//用户操作接口
public interface UserService {//根据ID查询用户Mono<User> getUserById(int id);//查询所有用户Flux<User> getAllUser();//添加用户Mono<Void> saveUserInfo(Mono<User> user);
}@Repository
public class UserServiceImpl implements UserService {//创建Map集合存储数据private final Map<Integer,User> users = new HashMap<>();public UserServiceImpl(){this.users.put(1,new User("lucy","nan",20));this.users.put(2,new User("mary","nv",30));this.users.put(3,new User("jack","nv",50));}//根据ID查询@Overridepublic Mono<User> getUserById(int id) {return Mono.justOrEmpty((id));}//查询多个用户@Overridepublic Flux<User> getAllUser() {return Flux.fromIterable(this.users.values());//取出集合}//添加@Overridepublic Mono<Void> saveUserInfo(Mono<User> userMono) {return userMono.doOnNext(person ->{     //uesrMono中的值放到person中//向Map集合中放值int id = users.size()+1;users.put(id,person);}).pty());//清空里边的值}
}@RestController
public class UserController {@Autowiredprivate UserService userService;//id查询@GetMapping("/user/{id}")public Mono<User> getUserId(@PathVariable int id){UserById(id);}//查询所有@GetMapping("/user")public Flux<User> getUsers(){AllUser();}//添加@PostMapping("/saveuser")public Mono<Void> saveUser(@RequestBody User user){Mono<User> userMono = Mono.just(user);return userService.saveUserInfo(userMono);}
}

本文发布于:2024-01-29 01:59:33,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170646477811909.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23