Spring5

Spring5

IOC : 控制反转,把创建对象得过程交给spring来做就是。目的降低耦合。

xml

|xml方式配置。
FileSystemXmlApplicationContext      //用于加载系统盘里面的文件
ClassPathXmlApplivationContext      //用于加载类文件

|Spring创建对象。
id:创建得对象得标识
class:类得路径。

|Spring注入属性。
DI:是IOC得具体实现,就是依赖注入。
  set注入:
      <bean id = "jsm" class = "com.jsm.spring.book">
      <property name = "属性名" value="注入得值"/>
      </bean>
  有参构造注入:
      <bean id = "jsm" class = "com.jsm.spring.book">
      <constructor-arg name="属性名" value="注入得值"/>
      </bean>
  p名称空间注入(简化xml)
     首先加入p名称空间
     然后<bean id = "jsm" class = "com.jsm.spring.book" p:name="属性名" p:value="注入得值">

注入属性->调用外部bean(service调用dao层)
      <property name = "属性名" rel="外部bean"/>
      
|级联赋值->一对多的关系(内部bean)
   <bean id = "student" class = "com.jsm.student">
       <property name = "id" value = "01"/>
       <property name = "name" value = "jsm"/>
       <property name = "dept">
         <bean id = "dept" class = "com.jsm.dept">
           <property name = "dept" value = "贾老师">
       </property>
   </bean>
   写法一:
   <bean id = "student" class = "com.jsm.student">
       <property name = "id" value = "01"/>
       <property name = "name" value = "jsm"/>
       <property name = "内部bean对象.外部bean属性名" value= "贾老师"/>
   </bean>
   
|xml反式注入集合属性
  数组类型属性:
     <bean id = "stu" calss = "com.jsm.student">
          <property name = "courses">
            <array>
                <value>java</value>
                <value>java2</value>
            </array>
      </bean>
      
  list集合属性:
     <bean id = "stu" calss = "com.jsm.student">
          <property name = "list">
            <list>
                <value>java</value>
                <value>java2</value>
            </list>
      </bean>
      
  map集合属性:
      <bean id = "stu" calss = "com.jsm.student">
          <property name = "maps">
            <map>
                <entry key = "JAVA" value = "java"></entry>
                <entry key = "JAVA1" value = "java1"></entry>
            </map>
      </bean>
      
   set集合属性:
        <bean id = "stu" calss = "com.jsm.student">
          <property name = "list">
            <set>
                <value>java</value>
                <value>java2</value>
            </set>
         </bean>

集合里面是对象类型的情况
    <bean id = "stu" calss = "com.jsm.student">
          <property name = "list">
            <list>
                <ref bean = "对象1"/>
                <ref bean = "对象2"/>
            </list>
      </bean>
    
|集合注入的部分提取出来,作为公共部分
    1.首先引入util名称空间
    2.如何提取
      <util:list id = "booklist">
          <value></value>
          <ref></ref>
      </util:list>
    3.如何使用
        <bean id = "book" class = "com.jsm.Book">
            <property bane = "list" ref = "booklist"/>
        </bean>
|FactoryBean工厂bean。
    定义类型和返回类型可能不一样而普通bean定义什么类型就是什么类型

|如何做?
    1.创建一个类作为工厂bean,实现接口FactoryBean
    2.实现接口里的方法,在方法中定义返回的bean的类型。
    
|bean的作用域。
    指的是bean实例是单实例还是多实例scope("prototype")
|单实例与多实例的区别
    单:加载CPAC的时候会创建对象
    多:getBean的时候才会创建对象
|bean的生命周期。7步
    1.执行无参构造创建bean实例
    2.调用set方法设置属性值
      把bean实例传递给bean后置处理器方法
    3.执行初始化的方法
      把bean实例传递给bean后置处理器方法
    4.获取创建bean实例对象
    5.执行销毁方法
|自动注入autowrid
    有两个属性根据name(id和属性名一致)和根据数据类型

|外部属性文件的引入
    1.引入名称空间context
    2.<context:property-placcholder location = "classpath:jdbc.properties"/>

注解

|@Component
    普通
|@Service
    业务逻辑serivice    
|@Controller
    web
|@Repository
    dao
|上面的注解功能相同
@RestController注解相当于@ResponseBody + @Controller合在一起的作用
@PathVariable接收占位符中的值/user/{id}
|首先开启组件扫描
    <context:component-scan base-package="com.jsm"/>

|扫描指定的包
    <context:component-scan base-package="com.jsm">
        <context:include-filter type = "annotion"
            expression = "com.jsm.Controller"/>
    </context>
    
|不扫描指定的包
    <context:component-scan base-package = "com.jsm">
        <context:exclude-filter type = "annotion"
            experssion = "com.jsm.Controller"
    </context>
|属性注入
    @Autowired    //根据类型注入
    @Qualifier    //根据属性名称注入(实现类不同就用实现类的名称注入与Autowired一起使用)
    @Resource(name = "")    //上面两个都可以
    @Value(value ="")    
    
    
|完全注解开发
   首先创建一个配置类,相当于xml。"
   配置类上加 @Configuration 和 @ComponentScan(basePackages="包名")
   

AOP

:面向切面,在不修改源代码得情况下,增强功能就是。

|AOP是什么?
    面向切面编程:可以对业务逻辑的各个部分分离开来。降低耦合度。

|底层原理?
    使用动态代理
    1.有接口的情况:jdk动态代理
       
    2.没有接口的时候:cglib动态代理
    
|AOP术语
    1.连接点
        类里面哪些方法可以被增强,这些方法称为连接点
    2.切入点
        实际被真正增强的方法,称为切入点
    3.通知(增强)
        实际增强的逻辑部分称为通知
        通知有多种类型
            前置通知 @Before 
            后置通知 @AfterReturnning 有异常不执行
            环绕通知 @Around
            异常通知 @AfterThrowing
            最终通知 @After 有异常也通知
    4.切面 :是动作
        把通知应用到切入点的过程
|AOP准备
    基于AspactJ实现AOP操作
          基于xml
             
          基于注解
             @Configuration
             @ComponentScan
             @EnableAspectJAutoPRoxy(proxyTargetClass = rtue)
|切入点表达式
    是为了知道哪个类里面的哪个方法进行增强
  语法结构
     execution([权限修饰符][返回类型][类全路径][方法名称]([参数列表])
   举例1:对com.jsm.dao.BookDao类里面的add进行增强
         execution(* com.jsm.dao.BookDao.add(..))
   举例2:所有方法增强
         execution(* com.jsm.dao.BookDao.*(..))
   举例3:所有类所有方法增强
         execution(* com.jsm.dao.*.*(..))

|相同切入点
    @Pointcut(value = "excution(com.jsm.dao.BookDao.add(..)")
    用的时候直接加上方法名
    @Before(value="add()")
|多个增强类增强一个方法
    执行的先后顺序:@Order(数值) 越小优先级约高

jdbcTemplate

|什么是jdbcTemplate?
    Spring对jdbc进行封装。
|准备工作
    引入包
    xml
    <context:component-scan base-package="com.jsm"/>
   <context:property-placeholder location="classpath*:DS.properties"/>
    <beans>
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
            <property name="driverClassName" value="${druid.driverClassName}"/>
            <property name="url" value="${druid.url}"/>
            <property name="name" value="${druid.name}"/>
            <property name="password" value="${druid.password}"/>
        </bean>
        <bean id="jdbcTemplate" class = "org.springframework.jdbc.core.JdbcTemplate">
               <property name="dataSource" ref="dataSource"/>
        </bean>
        
        配置
        dao
     
        service
  在查询对象时,用queryForObject(sql,new BeanPropertyRowMapper<Book>(Book.clss),id)
  批量操作,batchUpdate(sql,List<Object[]>)

事务管理

|使用声明式事务管理
   1.基于注解
   2.基于配置文件

|Spring事务管理API
    1.提供一个接口,代表事务管理器,底层使用AOP原理
        DataSourceTransactionManager
|事务操作注解
    1.在spring配置文件中配置事务管理器
      <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"/>
        </bean>
    2.加入名称空间tx,开启事务注解
    <tx:annotation-driven transctionmanager="transactionManaver"/>
    3.在service类上面加事务注解
        @Transactionl 也可以加在方法上面

|参数配置
    1.在service类上面添加注解@Transactional()配置相关参数
        propagation:事务的传播行为:多事务方法(对数据库中表中数据发生变化)之间的调用。required->如果有事务则在此事务中方运行。
        ioslation:事务的隔离级别:脏读->未提交的事务读到另一条未提交的事务。不可重复读->未提交事务读到了另一个已经提交事务中的修改的数据。幻读:未提交事务读到了另一个已经提交事务中的添加的数据。
        timeout:超时时间:事务需要早一定时间内进行提交,如果不提交就回滚。
        readOnly:是否只读
        rollbackFor:回滚
        norollback for:不回滚
|事务操作xml
   1.创建事务管理器
       <bean id = "transactionManager" class = "org.springframwork.jdbc.datasource.DataSourceTranscationManager">
           <property name = "dataSource" ref = "dataSource"/>
       </bean>
   2.配置通知
    <tx:advice id "txadvice">
        <tx:attributes>
            <tx:method name = "account*" propagation = "REQUIRED" islation ="">
        </tx:attributes>
    </tx:advice>
   3.配置切入点和切面
       <aop:config>
           <aop:pointcut id = "pt" expression ="execution(* com.jsm.service.UserService.*(..))"/>
           //配置切面
           <aop:advisor advice-ref = "txadvice" pointcut-ref = "pt"/>
       </aop:config>

日志

|首先引入log42 pom.xml   spring默认的是logback
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
            <version>2.6.4</version>
            <exclusions><!-- 去掉springboot默认配置 -->
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        
        
|配置log4j2.xml(文件名固定)
        <?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>
        
|测试
    private static final Logger log= LoggerFactory.getLogger(TestLog.class);

    public static void main(String[] args) {
        log.info("jjsjsjs");
        log.warn("jjjjjjjjj");
    }

Spring5核心容器

|@Nullable 
    表示属性方法类可以为空
    
|函数式风格创建对象,交给spring进行管理
    GenericApplicationContext context = new GenericAppcationContext();
    context.refresh();
    context.registerBean("user1",User.class,() -> new User());
    //获取在spring注册的对象
    User user = (User)context.getBean("com.jsm.spring5.User");
    //或者这样
    User user = (User)context.getBean("user1");
    

junit

|junit5
  @SpringJUnitConfig(location = ".xml")
|junit4
   @RunWith(SpringJUnit4ClassRunner.class)
   @ContextConfiguration(location = {"classpath*:/*.xml"})

Webflux

|异步和同步
    调用者发送请求,如果等着对方回应之后才去做其他事情就是同步,如果发送请求之后不等着对方回应就去做其他事情就是异步。
    
|阻塞和非阻塞针对被调用者,
    被调用者受到请求之后,做完请求任务之后才给吃反馈就是阻塞,受到请求之后马上给出反馈再去做事情就是非阻塞
    
|什么是响应式编程
    例如电子表格,包含公式的单元格会动态变化。
|如何实现响应式
    观察者模式:观察数据的变化发出通知做出响应。有Obeserver和Observable两个类
    
|Webflux的特点
    非阻塞式:在有限的资源下可以处理更多的请求,以Reactor为基础实现响应式编程
    函数式编程::实现路由请求。
|与SpringMVC的不同
    都可以使用注解方式,都运行在tomcat等容器中
    Webflux异步响应式编程,
    如何选取用哪个:
|响应式编程(Reactor实现)
   Reactor有两个核心的类,Mono和Flux,实现接口Publisher,提供了丰富的操作符。Flyx对象实现发布者,返回N个元素;Mono实现发布者,返回0或者1个元素
   
|Flux和Mono可以发出三种数据信号
    元素值,错误信号,完成信号。终止信号用于告诉订阅者数据流结束了。
    
|操作步骤:
    引入依赖
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-core</artifactId>
            <version>3.1.5.RELEASE</version>
        </dependency>
    创建类
    //just只是声明,数据流并没有输出,必须调用subscribe订阅才生效。
        Flux.just(1,2,3,4).subscribe();
        Mono.just(1).subscribe();
        
        Integer[] array = {1,2,3,4};
        Flux.fromArray(array);
        
        List<Integer> list = Arrays.aslist(array);
        Flux.fromIterable(list);
        
        Stream<Integer> stream = list.stream();
        Flux.fromStream(steam);
        
|操作符
    对数据流进行操作,
        map 元素映射为新的元素
        flatmap 元素映射为流:把多个流合成一个大流。
|SpringWebflux核心控制器(dispatchHandler)基于Reactor,默认使用的容器是Netty,它是高性能的NIO框架,非阻塞方式 
    HandlerMapping通过请求去找方法
    HandlerAdapter实现具体的业务方法
    HandlerResultHandler响应结果处理
    
|实现函数式编程,两个接口RouterFuntion(路由处理)和HandlerFuntion(处理函数)

|SpringWebflux实现方式有两种:注解和函数式
    注解:
        首先添加pom依赖
             <dependency>
                 <groupId>org.springframework.boot</groupId>
                 <artifactId>spring-boot-starter-webflux</artifactId>
             </dependency>
        设置端口号
            在properties里server.port=8081
            
        编写实体类
                @Data
                @AllArgsConstructor
                @NoArgsConstructor
                public class User {
                    private int id;
                    private String name;
                    private String address;
                }
                
                
        service:
           public interface UserService {
                //根据id查询
                 Mono<User> getUserById(int id);

                //查询所有
                Flux<User> getAllUsers();

                //添加用户
                Mono<Void> addUsers(Mono<User> user);
                           }
         serviceimpl:                    
@Repository
public class UserServiceImpl implements UserService {
    private final Map<Integer,User> map = new HashMap<>();

    public UserServiceImpl(){
        this.map.put(1,new User(1,"jsm","河南"));
        this.map.put(2,new User(2,"jsm1","河南1"));
        this.map.put(3,new User(3,"jsm2","河南2"));
    }

    @Override
    public Mono<User> getUserById(int id) {
        return Mono.just(this.map.get(id));
    }

    @Override
    public Flux<User> getAllUsers() {
        return Flux.fromIterable(this.map.values());
    }

    @Override
    public Mono<Void> addUsers(Mono<User> user) {
        return user.doOnNext(person->{
            int id = this.map.size()+1;
            this.map.put(id,person);

        }).then(Mono.empty());
    }

}
        
       controller:
@RestController
public class UserController {

    @Autowired
   private UserService userService;

    //id查询
    @GetMapping("/user/{id}")
    public Mono<User> getUserById(@PathVariable int id){
        return userService.getUserById(id);
    }
    //查询全部
    @GetMapping("/user")
    public Flux<User> getAllUsers(){
        return userService.getAllUsers();
    }
    //添加用户
    @PostMapping("/saveUser")
    public Mono<Void> addUsers(@RequestBody User user){
        Mono<User> userMono = Mono.just(user);
        return userService.addUsers(userMono);
    }

}
|基于函数式编程实现响应式编程
   实现函数式编程,两个接口RouterFuntion(路由处理)和HandlerFuntion(处理函数)
   SpringWebflux响应为serverRequest和ServerResponse
        同注解 然后编写Handler
            public class UserHandler {
    private final UserService userService;

    public UserHandler(UserService userService) {
        this.userService = userService;
    }

    //根究id查询
    public Mono<ServerResponse> getUserById(ServerRequest request) {
        //id
        int userId = Integer.parseInt(request.pathVariable("id"));
        //空值处理
        Mono<ServerResponse> notFound = ServerResponse.notFound().build();
        //调用service方法得到数据
        Mono<User> userMono =this.userService.getUserById(userId);
        return
               userMono.flatMap(person->ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(fromObject(person)))
                       .switchIfEmpty(notFound);
    }

    //查询所有
    public Mono<ServerResponse> getAllUsers(ServerRequest request){
        //调用service
        Flux<User> users = this.userService.getAllUsers();
        return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(users,User.class);
    }

    //添加
    public Mono<ServerResponse> saveUser(ServerRequest request){
        //的到User对象
        Mono<User> userMono = request.bodyToMono(User.class);
        return ServerResponse.ok().build(this.userService.addUser(userMono));
    }
}


|编写server类
      //3最终调用
    @SneakyThrows
    public static void main(String[] args) {
        server server = new server();
        server.createReactorServer();
        System.out.println("enter to exit");
        System.in.read();
    }

    //1创建Router路由
    public RouterFunction<ServerResponse> routingFunction(){
        UserService userService = new UserServiceImpl();
        UserHandler handler = new UserHandler(userService);
        return RouterFunctions.route(
               GET("/users/{id}").and(accept(MediaType.APPLICATION_JSON)),handler::getUserById)
                .andRoute(GET("/users").and(accept(MediaType.APPLICATION_JSON)),handler::getAllUsers);
    }

    //2创建服务器完成适配
    public void createReactorServer(){
        //路由和handler适配
        RouterFunction<ServerResponse> route = routingFunction();
        HttpHandler httpHandler = toHttpHandler(route);
        ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
        //创建服务器
        HttpServer httpServer = HttpServer.create();
        httpServer.handle(adapter).bindNow();
    }
}



|服务器测试,不用浏览器测试
    public class Client {

    public static void main(String[] args) {
        //调用服务器的地址
        WebClient webClient = WebClient.create("http://127.0.0.1:5794");

        //根据id查询
        String id = "1";
       User userresult =  webClient.get().uri("/users/{id}",id).accept(MediaType.APPLICATION_JSON).retrieve().bodyToMono(User.class)
                .block();
        System.out.println(userresult.getName());

        //查询所有
        Flux<User> userFlux = webClient.get().uri("/users")
                .accept(MediaType.APPLICATION_JSON)
                .retrieve().bodyToFlux(User.class);
        userFlux.map(stu->stu.getName())
                .buffer().doOnNext(System.out::println);
    }
}

public static void main(String[] args) {
//调用服务器的地址
WebClient webClient = WebClient.create(“http://127.0.0.1:5794”);

    //根据id查询
    String id = "1";
   User userresult =  webClient.get().uri("/users/{id}",id).accept(MediaType.APPLICATION_JSON).retrieve().bodyToMono(User.class)
            .block();
    System.out.println(userresult.getName());

    //查询所有
    Flux<User> userFlux = webClient.get().uri("/users")
            .accept(MediaType.APPLICATION_JSON)
            .retrieve().bodyToFlux(User.class);
    userFlux.map(stu->stu.getName())
            .buffer().doOnNext(System.out::println);
}

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值