Spring学习笔记2:注解开发、AOP思想、整合Mybatis、事务

2023-11-17

文章目录

7、使用注解开发

Spring4之后,要使用注解开发,必须导入AOP包,使用注解,必须导入context约束,增加注解支持

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--指定要扫描的包,这个包下的注解就会生效-->
    <context:component-scan base-package="com.atctbu.Dao"/>
    <context:annotation-config/>
</beans>

7.1、属性如何注入

1、@Component

​ 组件,放在类上说明这个类被Spring管理了,就是bean!

package com.atctbu.Dao;

import org.springframework.stereotype.Component;

//等价于<bean id="user" class="com.atctbu.Dao.User"/>
//@Component 组件
@Component
public class User {
    public String name ="何锦涛";
}
//最后测试能输出name
2、@Value
@Component
public class User {
    //相当于<property name="name" value="kuangshen"/>
    @Value("何锦涛")
    public String name ;
}

7.2、衍生的注解

​ @Component有几个衍生的注解,在我们web开发中,会按照mvc三层架构分层!

  • Dao【@Repository】
  • service 【@Service】
  • controller 【@Controller】

这四个注解功能都是一样的,都是代表某类注册到Spring中,装配Bean

7.3、自动装配

@Autowaired(required = false)//如果显示定义了Autowired的required属性为false,说明这个对象可以为null,否则不允许为空。

@Qualifier(value="dog222") 当使用@Autowired自动装配的环境比较复杂(有多个猫猫狗狗的时候),自动装配无法通过一个注解【@Autowired】完成的时候,使用@Qualifier(value="dog222"),去配合Autowired的使用,给它指定一个实现的值(bean对象)
    
@Nullable:字段标记了这个注解,说明这个字段可以为null;
    
@Resource:先通过名字查找,名字找不到根据类型查找,都找不到就报错,(有多个猫猫狗狗好像不行)@Resource(name = "cat2"),可以指定找哪个

7.4、作用域

1、@Scope(“singleton”)

​ 配置作用域,和bean里面配置一样的

7.5、小结

xml与注解:

  • xml更加万能,适用于任何场合!维护简单方便
  • 注解不是自己类使用不了,维护相对复杂!

xml与注解最佳实践:

  • xml用来管理bean;
  • 注解只负责完成属性的注入;
  • 我们在使用的过程中,只需要注意一个问题: 必须让注解生效,就需要开启注解的支持
<!--指定要扫描的包,这个包下的注解就会生效-->
<context:component-scan base-package="com.atctbu.Dao"/>
<context:annotation-config/>

9、使用java的方式配置Spring

​ 我们现在要完全不使用Spring的xml配置了,全权交给java来做!

​ JavaConfig是Spring的一个子项目,在Spring 4之后,它成为了核心功能

9.1、实体类User

package com.atctbu.pojo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

//说明这个类被Spring接管了,注册到了容器中
@Component
public class User {
    private String name;

    public String getName() {
        return name;
    }
    @Value("何锦涛07")//注入值
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }
}

9.2、配置文件MyConfig

package com.atctbu.config;

import com.atctbu.poji.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Component;

//也会被Spring容器托管,注册到容器中,因为他本来就是一个Component,@Configuration代表这是一个配置类,和我们之前看的beans.xml是一样的
@Configuration
@ComponentScan("com.atctbu.pojo")
@Import(MyConfig2.class)
public class MyConfig {

    //注册一个Bean,就相当于我们之前写的一个Bean标签,
    //这个方法的名字,就相当于bean标签中的id属性
    //这个方法的返回值,就相当于bean标签中的class属性
    @Bean
    public User getUser(){
        return new User();//就是返回值要注入的bean对象
    }
}

9.3、MyConfig2

package com.atctbu.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
public class MyConfig2 {
}

9.4、测试类MyTest07

import com.atctbu.config.MyConfig;
import com.atctbu.poji.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MyTest07 {
    public static void main(String[] args) {
        //如果完全使用了配置类方式去做,我们就只能通过AnnotationConfig上下文来获取容器,通过类的class对象加载!
        ApplicationContext Context = new AnnotationConfigApplicationContext(MyConfig.class);
//        User getUser = Context.getBean("getUser", User.class);
        User getUser = Context.getBean("user", User.class);    //加了@ComponentScan后可以使用
        System.out.println(getUser.getName());
    }
}

​ 这种纯java的配置方式,在SpringBoot中随处可见!

10、代理模式

​ 为什么要学习代理模式?因为这就是SpringAOP的底层!【SpringAOP和SpringMVC:面试必问】

10.1、静态代理

角色分析:

● 抽象角色:一般会使用接口或者抽象类来解决
● 真实角色:被代理的角色
● 代理角色:代理真实角色,代理真实角色后,我们一-般会做-一些附属操作
● 客户:访问代理对象的人!

10.1.1、代码步骤

1.接口

package com.atctbu.demo01;


//租房接口
public interface Rent {
    public void rent();
}

2.真实角色

package com.atctbu.demo01;


//房东
public class Host implements Rent{

    public void rent() {
        System.out.println("房东要出租房子!");
    }
}

3.代理角色

package com.atctbu.demo01;

public class Proxy implements Rent{
    private Host host;
    
    public Proxy() {
    }
    
    public Proxy(Host host) {
        this.host = host;
    }

    public void rent() {
        host.rent();
        seeHouse();
        hetong();
        fare();
    }

    //看房
    public void seeHouse(){
        System.out.println("中介带你看房");
    }
    //合同
    public void hetong(){
        System.out.println("中介签合同");
    }
    //收中介费
    public void fare(){
        System.out.println("收中介费");
    }
}

4.客户端访问代理角色

package com.atctbu.demo01;

public class Client {
    public static void main(String[] args) {
        //房东租房子
        Host host = new Host();
        //代理,中介帮房东租房子,但是呢,中介总有一些中间附属操作
        Proxy proxy = new Proxy(host);
        //你不用面对房东,直接找中介租房
        proxy.rent();
    }
}
10.1.2、代理模式(静态)的好处:

● 可以使真实角色的操作更加纯粹!不用去关注一 些公共的业务
● 公共也就就交给代理角色!实现了业务的分工!
● 公共业务发生扩展的时候,方便集中管理!

缺点:

● 一个真实角色就会产生一个代理角色;代码量会翻倍,开发效率会变低

10.1.3、静态代理加深

1.接口

package com.atctbu.demo02;

public interface UserService {
    public void add();
    public void delete();
    public void update();
    public void query();
}

2、真实角色

package com.atctbu.demo02;

public class UserServiceImpl implements UserService{
    public void add() {
        System.out.println("增加了一个用户");
    }

    public void delete() {
        System.out.println("删除了一个用户");
    }

    public void update() {
        System.out.println("修改了一个用户");
    }

    public void query() {
        System.out.println("查询了一个用户");
    }
}

3、代理角色

package com.atctbu.demo02;

public class UserServiceProxy implements UserService{

    private UserServiceImpl userService;

    public void setUserService(UserServiceImpl userService) {
        this.userService = userService;
    }

    public void add() {
        log("add");
        userService.add();
    }

    public void delete() {
        log("delete");
        userService.delete();
    }

    public void update() {
        log("update");
        userService.update();
    }

    public void query() {
        log("query");
        userService.query();
    }

    //日志方法
    public void log(String msg){
        System.out.println("使用了" + msg + "方法");
    }
}

4、测试

package com.atctbu.demo02;

public class Client {
    public static void main(String[] args) {
        UserServiceImpl userService = new UserServiceImpl();
        UserServiceProxy proxy = new UserServiceProxy();
        proxy.setUserService(userService);

        proxy.add();
    }
}

/*
使用了add方法
增加了一个用户
*/

10.2、动态代理

  • 动态代理和静态代理角色一样
  • 动态代理的代理类是动态生成的,不是我们直接写好的!
  • 动态代理分为两大类:基于接口的动态代理,基于类的动态代理
    • 基于接口—JDK动态代理【我们在这里使用】
    • 基于类: cglib
    • java字节码实现: JAVAssist

需要了解两个类:Proxy:代理,InvocationHandler:调用处理程序

动态代理的好处:

  • 可以使真实角色的操作更加纯粹!不用去关注一 些公共的业务!
  • 公共也就就交给代理角色!实现了业务的分工!
  • 公共业务发生扩展的时候,方便集中管理!
  • 一个动态代理类代理的是一个接口,一般就是对应的一类业务!
  • 一个动态代理类可以代理多个类,只要是实现了同一个接口即可!
10.2.1、例子:

1、接口

package com.atctbu.demo03;
//租房接口
public interface Rent {
    public void rent();
}

2、真实角色

package com.atctbu.demo03;
//房东
public class Host implements Rent {

    public void rent() {
        System.out.println("房东要出租房子!");
    }
}

3、测试类

package com.atctbu.demo03;

public class Client {
    public static void main(String[] args) {
        //真实角色
        Host host = new Host();

        //代理角色:现在没有
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        //通过调用程序处理角色来处理我们要调用的接口对象
        pih.setRent(host);
        Rent proxy = (Rent)pih.getProxy();  //这里的proxy就是动态生成的,我们并没有去写它
        proxy.rent();
    }
}

4、代理类

package com.atctbu.demo03;

import java.lang.reflect.Proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

//等我们会用这个类,自动生成代理类!
public class ProxyInvocationHandler implements InvocationHandler {

    //被代理的接口
    private Rent rent;

    public void setRent(Rent rent) {
        this.rent = rent;
    }

    //生成得到代理类
    public Object getProxy(){
        //固定的代码,死的,只需要改rent、getClassLoader()加载到类在哪个位置、
        // getInterfaces(),表示它要代理的接口是哪个接口
        //this、代表自己:InvocationHandler
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                rent.getClass().getInterfaces(),this);
    }

    //处理代理实例,并返回结果,真正处理invoke负责执行真正要处理的方法
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //动态代理的本质,就是使用反射机制实现!
        seeHouse();
        Object result = method.invoke(rent, args);
        fare();
        return result;
    }

    public void seeHouse(){
        System.out.println("中介看房子");
    }
    public void fare(){
        System.out.println("收中介费");
    }
}
10.2.2、万能模板

1、万能模板

package com.atctbu.demo04;

import com.atctbu.demo03.Rent;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

//等我们会用这个类,自动生成代理类!
public class ProxyInvocationHandler implements InvocationHandler {

    //被代理的接口
    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }

    //生成得到代理类
    public Object getProxy(){
        //固定的代码,死的,只需要改rent、getClassLoader()加载到类在哪个位置、
        // getInterfaces(),表示它要代理的接口是哪个接口
        //this、代表自己:InvocationHandler
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                target.getClass().getInterfaces(),this);
    }

    //处理代理实例,并返回结果,真正处理invoke负责执行真正要处理的方法
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //动态代理的本质,就是使用反射机制实现!
        log(method.getName());
        Object result = method.invoke(target, args);
        return result;
    }

    public void log(String msg){
        System.out.println("执行了"+ msg + "方法");
    }
}

2、测试类

package com.atctbu.demo04;

import com.atctbu.demo02.UserService;
import com.atctbu.demo02.UserServiceImpl;

public class Client {
    public static void main(String[] args) {
        //真实角色
        UserServiceImpl userService = new UserServiceImpl();
        //代理角色
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        pih.setTarget(userService);//设置要代理的对象
        //动态生成代理类
        UserService proxy = (UserService) pih.getProxy();
        proxy.add();
    }
}
/*
执行了add方法
增加了一个用户
*/

11、AOP

11.1、什么是AOP

AOP (Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一护的一种技术。AOP是0OP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

业务逻辑

验证参数 验证参数 验证参数 验证参数
前置日志 前置日志 前置日志 前置日志 代理对象
add() sub( ) mul( ) div( )
后置日志 后置日志 后置日志 后置日志

​ 抽取横切关注点↓ AOP↑

验证 日志 业务逻辑
验证参数 前置日志 后置日志 add() div( )
sub() mul( ) 目标对象
切面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CjNC7yrE-1617159142188)(C:\Users\何锦涛\AppData\Roaming\Typora\typora-user-images\image-20201117185153564.png)]

11.2、AOP在Spring中的作用

提供声明式事务;允许用户自定义切面

●横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如日志,安全,缓存,事务等等…

●切面(ASPECT) :横切关注点被模块化的特殊对象。即,它是一 个类。

●通知(Advice) :切面必须要完成的工作。即,它是类中的-一个方法。

●目标(Target) :被通知对象。

●代理(Proxy) :向目标对象应用通知之后创建的对象。

●切入点(PointCut) :切面通知执行的“地点”的定义。

●连接点(ointPoint) :与切入点匹配的执行点。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-witIyfRi-1617159142190)(C:\Users\何锦涛\AppData\Roaming\Typora\typora-user-images\image-20201117185416473.png)]

​ SpringAOP中,通过Advice定义横切逻辑,Spring中支持5种类型的Advice:

通知类型 连接点 实现接口

前置通知 方法方法前 org. springframework aop.MethodBeforeAdvice
后置通知 方法后 org.springframework. aop AfterReturningAdvice
环绕通知 方法前后 org.aopalliance.interceptMethodInterceptor
异常抛出通知 方法抛出异常 org.springframework. aop.ThrowsAdvice
引介通知 类中增加新的方法属性 org-springframework.aop IntroductionInterceptor

即Aop在不改变原有代码的情况下,去增加新的功能.

11.3、使用Spring实现AOP

【重点】使用AOP织入,需要导入一个依赖包!

<!-- https://mvnrepository. com/artifact/org. aspectj/aspectjweaver -->
<dependency>
	<groupId>org.aspectj</groupId>
	<artifactId>aspectjweaver</artifactId>
	<version>1.9.6</version>
</dependency>
11.3.1、方式一:使用Spring的API接口【主要是SpringAPI接口实现】

1、接口

package com.atctbu.service;

public interface UserService {
    public void add();
    public void delete();
    public void update();
    public void select();
}

2、实现类

package com.atctbu.service;

public class UserServiceImpl implements UserService {
    public void add() {
        System.out.println("增加了一个用户!");
    }

    public void delete() {
        System.out.println("删除了一个用户!");
    }

    public void update() {
        System.out.println("更新了一个用户!");
    }

    public void select() {
        System.out.println("选择了一个用户!");
    }
}

3、前置

package com.atctbu.log;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;
//前置
public class Log implements MethodBeforeAdvice {

    //method:要执行的目标对象的方法、objects/args:参数、target/o:目标对象
    //这个方法会在执行方法前自动调用
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass().getName() + "的" + method.getName() + "被执行了");
    }
}

4、后置

package com.atctbu.log;

import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;
//后置
public class Afterlog implements AfterReturningAdvice {

    //o/returnValue:返回值
    public void afterReturning(Object returnValue, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("执行了:" + method.getName() + "方法,返回结果为:" + returnValue);
    }
}

5、测试

import com.atctbu.service.UserService;
import com.atctbu.service.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Mytest09 {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //动态代理代理的是接口,注意点
        UserService userService = context.getBean("userService", UserService.class);

        userService.add();
    }
}
/*
com.atctbu.service.UserServiceImpl的add被执行了
增加了一个用户!
执行了:add方法,返回结果为:null
*/

6、applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

     <!--注册bean-->
    <bean id="userService" class="com.atctbu.service.UserServiceImpl"/>
    <bean id="log" class="com.atctbu.log.Log"/>
    <bean id="afterLog" class="com.atctbu.log.Afterlog"/>

    <!--配置AOP,alt+enter,需要导入AOP的约束-->
    <aop:config>
        <!--切入点:expression:表达式、execution(要执行的位置!*******)、*代表任意的类-->
        <!--.*(..):.*代表所有的方法:..代表可以有任意的参数-->
        <!--execution表达式:可百度-->
        <aop:pointcut id="pointcut" expression="execution(* com.atctbu.service.UserServiceImpl.*(..))"/>
        <!--执行环绕增加!-->
        <!--把log这个类切入到上面这个方法上面-->
        <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
    </aop:config>
</beans>
11.3.2、方式二:自定义类实现AOP【主要是切面定义】

1、applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

     <!--注册bean-->
    <bean id="userService" class="com.atctbu.service.UserServiceImpl"/>
    <bean id="log" class="com.atctbu.log.Log"/>
    <bean id="afterLog" class="com.atctbu.log.Afterlog"/>

    <!--配置AOP,alt+enter,需要导入AOP的约束-->
<!--    <aop:config>-->
<!--        &lt;!&ndash;切入点:expression:表达式、execution(要执行的位置!*******)、*代表任意的类&ndash;&gt;-->
<!--        &lt;!&ndash;.*(..):.*代表所有的方法:..代表可以有任意的参数&ndash;&gt;-->
<!--        <aop:pointcut id="pointcut" expression="execution(* com.atctbu.service.UserServiceImpl.*(..))"/>-->
<!--        &lt;!&ndash;执行环绕增加!&ndash;&gt;-->
<!--        &lt;!&ndash;把log这个类切入到上面这个方法上面&ndash;&gt;-->
<!--        <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>-->
<!--        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>-->
<!--    </aop:config>-->
    <!--方式二:自定义类-->
    <bean id="diy" class="com.atctbu.diy.DiyPointCut"/>
    <aop:config>
        <!--自定义切面,ref:要引用的类-->
        <aop:aspect ref="diy">
            <!--切入点-->
            <aop:pointcut id="point" expression="execution(* com.atctbu.service.UserServiceImpl.*(..))"/>
            <!--通知:before要执行什么方法-->
            <aop:before method="before" pointcut-ref="point"/>
            <aop:after method="after" pointcut-ref="point"/>
        </aop:aspect>
    </aop:config>
</beans>

2、DiyPointCut

package com.atctbu.diy;

public class DiyPointCut {
    public void before(){
        System.out.println("==========方法执行前==========");
    }
    public void after(){
        System.out.println("==========方法执行后==========");
    }
}

3、测试类

import com.atctbu.service.UserService;
import com.atctbu.service.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Mytest09 {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //动态代理代理的是接口,注意点
        UserService userService = context.getBean("userService", UserService.class);

        userService.add();
    }
}
/*
==========方法执行前==========
增加了一个用户!
==========方法执行后==========
*/
11.3.3、方式三:使用注解方式实现AOP
@Aspect //标志这个类是一个切面

1、AnnotationPointCut

package com.atctbu.diy;

//方式三:使用注解方式实现AOP

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect //标志这个类是一个切面
public class AnnotationPointCut {

    @Before("execution(* com.atctbu.service.UserServiceImpl.*(..))")//切入点
    public void before(){
        System.out.println("=====方法执行前=====");
    }
    @After("execution(* com.atctbu.service.UserServiceImpl.*(..))")
    public void after(){
        System.out.println("=====方法执行后=====");
    }
    //在环绕增强中,我们可以给定一个参数,代表我们要获取处理切入的点:
    @Around("execution(* com.atctbu.service.UserServiceImpl.*(..))")
    //JoinPoint:与切入点匹配的执行点
    public void around(ProceedingJoinPoint jp) throws Throwable {
        System.out.println("=====方法环绕前=====");
        Signature signature = jp.getSignature();//获得签名
        System.out.println("signature:" + signature);
        //执行方法
        Object proceed = jp.proceed();
        System.out.println("=====方法环绕后=====");
        System.out.println(proceed);
    }
}

2、测试类

import com.atctbu.service.UserService;
import com.atctbu.service.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Mytest09 {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //动态代理代理的是接口,注意点
        UserService userService = context.getBean("userService", UserService.class);

        userService.add();
    }
}

3、applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

     <!--注册bean-->
    <bean id="userService" class="com.atctbu.service.UserServiceImpl"/>
    <bean id="log" class="com.atctbu.log.Log"/>
    <bean id="afterLog" class="com.atctbu.log.Afterlog"/>

    <!--方式三-->
    <!--注册bean,也可以通过Component-->
    <bean id="annotationPointCut" class="com.atctbu.diy.AnnotationPointCut"/>
    <!--开启注解支持!     JDK(默认:proxy-target-class="false") cglib(proxy-target-class="true")-->
    <aop:aspectj-autoproxy/>
</beans>

12、整合Mybatis

步骤:

  1. 导入相关jar包

    • junit
    • mybatis
    • mysql数据库
    • spring相关的
    • aop织入
    • mybatis-spring【new】
    <dependencies>
        <!--mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.15</version>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
        </dependency>
        <!--junit驱动-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
        <!--Spring操作数据库的话,还需要一个Spring-JBDC-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.1</version>
        </dependency>
        <!--织入必须导这个-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.6</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.3</version>
        </dependency>
    </dependencies>
    
  2. 编写配置文件

  3. 测试

12.1、回忆Mybatis

1、编写实体类

2、编写核心配置文件

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
username=root
password=q1314159

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <properties resource="db.properties">
        <property name="username" value="root"/>
        <property name="password" value="q1314159"/>
    </properties>
    <!--配置别名-->
    <typeAliases>
        <package name="com.atctbu.hjt.pojo"/>
    </typeAliases>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper class="com.atctbu.hjt.dao.UserMapper"/>
    </mappers>
</configuration>

3、编写接口

4、编写Mapper.xml

<mapper namespace="com.atctbu.hjt.dao.UserMapper">
    <select id="selectUser" resultType="User">
        select * from mybatis.user
    </select>
</mapper>

5、测试

public void selectUser() throws IOException {
    String resources = "mybatis-config.xml";
    InputStream in = Resources.getResourceAsStream(resources);
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
    SqlSession sqlSession = sqlSessionFactory.openSession(true);

    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    List<User> userList = mapper.selectUser();
    for (User user:userList
        ) {
        System.out.println(user);
    }
}
User{id=1, name='何锦涛', pwd='123456'}
User{id=2, name='严瑶', pwd='123456'}
User{id=3, name='王大拿', pwd='12121212'}

12.2、mybatis-spring

​ MyBatis-Spring 会帮助你将 MyBatis 代码无缝地整合到 Spring 中。它将允许 MyBatis 参与到 Spring 的事务管理之中,创建映射器 mapper 和 SqlSession 并注入到 bean 中,以及将 Mybatis 的异常转换为 Spring 的 DataAccessException。 最终,可以做到应用代码不依赖于 MyBatis,Spring 或 MyBatis-Spring。

​ 要和 Spring 一起使用 MyBatis,需要在 Spring 应用上下文中定义至少两样东西:一个 SqlSessionFactory 和至少一个数据映射器类。

​ 在 MyBatis-Spring 中,可使用 SqlSessionFactoryBean来创建 SqlSessionFactory。 要配置这个工厂 bean,只需要把下面代码放在 Spring 的 XML 配置文件中:

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  <property name="dataSource" ref="dataSource" />
</bean>
12.2.1、具体操作
  1. 编写数据源配置

    spring-dao.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop.xsd">
    
        <!--DataSource:使用Spring的数据源替换Mybatis的配置     c3p0    dbcp    druid
        我们这里使用Spring提供的JBDC:"org.springframework.jdbc.datasource.DriverManagerDataSource
            ↑:这个东西是导入的spring-jbdc依赖
        -->
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=UTC"/>
            <property name="username" value="root"/>
            <property name="password" value="q1314159"/>
        </bean>
        
        <!--SqlSessionFactory-->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource" />
            <!--绑定Mybatis配置文件-->
            <property name="configLocation" value="classpath:mybatis-config.xml"/>
            <property name="mapperLocations" value="classpath:com/atctbu/hjt/dao/*.xml"/>
        </bean>
        
        <!--sqlSession:官方建议sqlSessionTemplate,这就是我们使用的sqLSession -->
        <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
            <!--只能使用构造器注入sqlSessionFactory,因为它没有set方法-->
            <constructor-arg index="0" ref="sqlSessionFactory"/>
        </bean>
    
        <!---->
    <!--    <bean id="userMapper" class="com.atctbu.hjt.dao.UserMapperImpl">-->
    <!--        <property name="sqlSession" ref="sqlSession"/>-->
    <!--    </bean>-->
    </beans>
    

    mybatis-config.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <!--配置别名-->
        <typeAliases>
            <package name="com.atctbu.hjt.pojo"/>
        </typeAliases>
        <!--设置-->
    
    </configuration>
    

    applicationContext.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop.xsd">
    
        <import resource="spring-dao.xml"/>
    
        <!---->
        <bean id="userMapper" class="com.atctbu.hjt.dao.UserMapperImpl">
            <property name="sqlSession" ref="sqlSession"/>
        </bean>
    </beans>
    
  2. SqlSessionFactory

  3. SqlSessionTemplate

  4. 需要给接口加实现类【】

    UserMapper.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.atctbu.hjt.dao.UserMapper">
        <select id="selectUser" resultType="User">
            select * from mybatis.user
        </select>
    </mapper>
    
    package com.atctbu.hjt.dao;
    
    import com.atctbu.hjt.pojo.User;
    import org.mybatis.spring.SqlSessionTemplate;
    
    import java.util.List;
    
    public class UserMapperImpl implements UserMapper{
    
        //原来我们的所有操作都使用SqlSession来执行,现在都使用SqlSessionTemplate;
        private SqlSessionTemplate sqlSession;
    
        public void setSqlSession(SqlSessionTemplate sqlSession) {
            this.sqlSession = sqlSession;
        }
    
        public List<User> selectUser() {
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            return mapper.selectUser();
        }
    }
    
  5. 将写的实现类注入到Spring中

  6. 测试

@Test
public void selectUser() throws IOException {
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
    List<User> userList = userMapper.selectUser();
    for (User user: userList
        ) {
        System.out.println(user);
    }
}
User{id=1, name='何锦涛', pwd='123456'}
User{id=2, name='严瑶', pwd='123456'}
User{id=3, name='王大拿', pwd='12121212'}

12.3、整合Mybatis方式二:SqlSessionDaoSupport

SqlSessionDaoSupport 是一个抽象的支持类,用来为你提供 SqlSession。调用 getSqlSession() 方法你会得到一个 SqlSessionTemplate,之后可以用于执行 SQL 方法,就像下面这样:

public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao {
    public User getUser(String userId) {
        return getSqlSession().selectOne("org.mybatis.spring.sample.mapper.UserMapper.getUser", userId);
    }
}

​ 在这个类里面,通常更倾向于使用 MapperFactoryBean,因为它不需要额外的代码。但是,如果你需要在 DAO 中做其它非 MyBatis 的工作或需要一个非抽象的实现类,那么这个类就很有用了。

SqlSessionDaoSupport 需要通过属性设置一个 sqlSessionFactorySqlSessionTemplate。如果两个属性都被设置了,那么 SqlSessionFactory 将被忽略。

​ 假设类 UserMapperImplSqlSessionDaoSupport 的子类,可以编写如下的 Spring 配置来执行设置:

<bean id="userDao" class="org.mybatis.spring.sample.dao.UserDaoImpl">
  <property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
12.3.1、具体操作

UserMapperImpl2

public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{
    public List<User> selectUser() {
        SqlSession sqlSession = getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        return mapper.selectUser();
    }
}

applicationContext.xml

<bean id="userMapper2" class="com.atctbu.hjt.dao.UserMapperImpl2">
    <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>

测试UserMapperImpl2

@Test
public void selectUser() throws IOException {
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    UserMapper userMapper = context.getBean("userMapper2", UserMapper.class);
    List<User> userList = userMapper.selectUser();
    for (User user: userList
        ) {
        System.out.println(user);
    }
}
//也能查出来结果

13、声明式事务

13.1、回顾事务

  • 要么都成功,要么都失败
  • 事务在项目开发中,十分重要。涉及数据一致性问题
  • 确保完整性和一致性

事务的ACID原则:

  • 原子性
  • 一致性
  • 隔离性
    • 多个业务可能操作同一个资源,防止数据损坏
  • 持久性
    • 事务一旦提交,无论系统发生什么问题,结果都不会再被影响,被持久化的写到存储器或数据库中!

将sql的删除语句故意写错

public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{
    public List<User> selectUser() {
        User user = new User(4,"小何","123456");
        UserMapper mapper1 = getSqlSession().getMapper(UserMapper.class);
        mapper1.addUser(user);
        mapper1.deleteUseer(4);
        return mapper1.selectUser();
    }

    public int addUser(User user) {
        SqlSession sqlSession = getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        return mapper.addUser(user);
    }

    public int deleteUseer(int id) {
        SqlSession sqlSession = getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        return mapper.deleteUseer(id);
    }
}

这个时候我们测试

public void Test(){
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    UserMapper userMapper2 = context.getBean("userMapper2", UserMapper.class);
    List<User> userList = userMapper2.selectUser();
    for (User user:userList
        ) {
        System.out.println(user);
    }
}

仍然插入成功了,我们并不希望插入成功

13.2、spring中的事务管理

  • 声明式事务:AOP
  • 编程式事务:需要在代码中进行事务的管理

思考:

为什么需要事务?

  • 如果不配置事务,可能存在数据提交不一致的情况
  • 如果不在Spring中取配置声明式事务,我们就需要在代码中手动配置事务!
  • 事务在项目的开发中十分重要,涉及到数据的一致性和完整性问题
13.2.1、标准配置(结合AOP织入事务)

要开启 Spring 的事务处理功能,在 Spring 的配置文件中创建一个 DataSourceTransactionManager 对象:

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <constructor-arg ref="dataSource" />
</bean>

我们在不改动原来的代码情况下配置事务的织入

例子:

spring-dao.xml中

<!--结合AOP实现事务的织入-->
<!--配置事务通知:-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <!--给哪些方法配置事务-->
    <!--配置事务的传播特性:new  propagation-->
    <tx:attributes>
        <tx:method name="add" propagation="REQUIRED"/>
        <tx:method name="delete" propagation="REQUIRED"/>
        <tx:method name="update" propagation="REQUIRED"/>
        <tx:method name="query" read-only="true"/>
        <tx:method name="*" propagation="REQUIRED"/>
    </tx:attributes>
</tx:advice>
<!--配置事务切入-->
<aop:config>
    <!--dao下的所有类所有方法都可以使用这个事务-->
    <aop:pointcut id="txPoingCut" expression="execution(* com.atctbu.hjt.dao.*.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="txPoingCut"/>
</aop:config>

再次运行错误的测试(删除错误)

//UserMapperImpl
public List<User> selectUser() {
    User user = new User(4,"小何","123456");
    UserMapper mapper1 = getSqlSession().getMapper(UserMapper.class);
    mapper1.addUser(user);
    mapper1.deleteUseer(4);
    return mapper1.selectUser();
}
@Test
public void Test(){
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    UserMapper userMapper2 = context.getBean("userMapper2", UserMapper.class);
    List<User> userList = userMapper2.selectUser();
    for (User user:userList
        ) {
        System.out.println(user);
    }
}

这时,执行失败,但是插入也没有成功

13.2.2、事务的传播:面试会考

**1、PROPAGATION_REQUIRED:**如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。

**2、PROPAGATION_SUPPORTS:**支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。‘

**3、PROPAGATION_MANDATORY:**支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。

**4、PROPAGATION_REQUIRES_NEW:**创建新事务,无论当前存不存在事务,都创建新事务。

**5、PROPAGATION_NOT_SUPPORTED:**以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

**6、PROPAGATION_NEVER:**以非事务方式执行,如果当前存在事务,则抛出异常。

**7、PROPAGATION_NESTED:**如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring学习笔记2:注解开发、AOP思想、整合Mybatis、事务 的相关文章

  • 使用 Ant 将非代码资源添加到 jar 文件

    我正在将 java 应用程序打包成 jar 文件 我正在使用 ant 和 eclipse 我实际上需要在 jar 中直接在根文件夹下包含几个单独的非代码文件 xml 和 txt 文件 而不是与代码位于同一位置 我正在尝试使用includes
  • Spring RestTemplate 使用 cookie 遵循重定向

    最近我遇到了一个问题 我需要做一个GET请求远程服务 我假设使用一个简单的 servlet 并且 RestTemplate 返回Too many redirects 经过一番调查 似乎对指定远程服务发出的第一个请求实际上只是一个 302 重
  • 在 Wildfly 中与 war 部署共享 util jar 文件

    假设我有一个名为 util jar 的 jar 文件 该 jar 文件主要包含 JPA 实体和一些 util 类 无 EJB 如何使这个 jar 可用于 Wildfly 中部署的所有 war 无需将 jar 放置在 war 的 WEB IN
  • 如何将 Mat (opencv) 转换为 INDArray (DL4J)?

    我希望任何人都可以帮助我解决这个任务 我正在处理一些图像分类并尝试将 OpenCv 3 2 0 和 DL4J 结合起来 我知道DL4J也包含Opencv 但我认为它没什么用 谁能帮我 如何转换成 INDArray 我尝试阅读一些问题here
  • 如何在代理后面安装 Eclipse Neon

    对于 Neon Eclipse 附带了一个安装程序 我在安装程序中找不到任何配置菜单 我的java版本是 java version java version 1 8 0 72 Java TM SE Runtime Environment b
  • 当客户端关闭连接时,Spring StreamingResponseBody 请求线程未清理

    我在控制器中有一个端点 它返回一个StreamingResponseBody 用于向客户端发送文件 其代码大致如下 RestController RequestMapping value api public class Controlle
  • Spring Security SAML2 使用 G Suite 作为 Idp

    我正在尝试使用 Spring Security 5 3 3 RELEASE 来处理 Spring Boot 应用程序中的 SAML2 身份验证 Spring Boot 应用程序将成为 SP G Suite 将成为 IDP 在我的 Maven
  • 自动生成Flyway的迁移SQL

    当通过 Java 代码添加新模型 字段等时 JPA Hibernate 的自动模式生成是否可以生成新的 Flyway 迁移 捕获自动生成的 SQL 并将其直接保存到新的 Flyway 迁移中 以供审查 编辑 提交到项目存储库 这将很有用 预
  • 从 GitHub 上托管的 Spring Cloud Config Server 访问存储库的身份验证问题

    我在 GitHub 上的存储库中托管配置 如果我将回购公开 一切都好 但如果我将其设为私有 我将面临 org eclipse jgit errors TransportException https github com my user m
  • Java Swing For mac 中的 DJ Native Swing 浏览器

    我有一个用 Swing 制作的 Java 应用程序 并且使用了一个 DJ Native Swing 浏览器 当我尝试在 OS X 上使用它时 它抛出了一个NoClassDefFoundError尽管我添加了 swt jar 但始终如此 有人
  • 如何避免 ArrayIndexOutOfBoundsException 或 IndexOutOfBoundsException? [复制]

    这个问题在这里已经有答案了 如果你的问题是我得到了java lang ArrayIndexOutOfBoundsException在我的代码中 我不明白为什么会发生这种情况 这意味着什么以及如何避免它 这应该是最全面的典范 https me
  • GWT 2.3 开发模式 - 托管模式 JSP 编译似乎不使用 java 1.5 兼容性

    无法编译 JSP 类 生成的 servlet 错误 DefaultMessage 上次更新 0 日期 中 0 时间 HH mm ss z 语法 错误 注释仅在源级别为 1 5 时可用 在尝试以开发模式在 Web 浏览器中打开我的 gwt 模
  • 在 SWT/JFace RCP 应用程序中填充巨大的表

    您将如何在 SWT 表中显示大量行 巨大是指超过 20K 行 20 列的东西 不要问我为什么需要展示那么多数据 这不是重点 关键是如何让它尽可能快地工作 这样最终用户就不会厌倦等待 每行显示某个对象的实例 列是其属性 一些 我想使用 JFa
  • 返回 Java 8 中的通用函数接口

    我想写一种函数工厂 它应该是一个函数 以不同的策略作为参数调用一次 它应该返回一个函数 该函数根据参数选择其中一种策略 该参数将由谓词实现 嗯 最好看看condition3为了更好的理解 问题是 它没有编译 我认为因为编译器无法弄清楚函数式
  • Spring-ws:如何从没有“Request”元素的 xsd 创建 Wsdl

    尝试为客户端实现 SOAP Web 服务 我需要一个 wsdl 文件来通过soapUI 测试该服务 但正如您在下面看到的 这个 xsd 没有 Request 和 Response 方法 所有请求和响应都被定义为基本 ServiceProvi
  • Java Swing:需要一个高质量的带有复选框的开发 JTree

    我一直在寻找一个 Tree 实现 其中包含复选框 其中 当您选择一个节点时 树中的所有后继节点都会被自动选择 当您取消选择一个节点时 树中其所有后继节点都会自动取消选择 当已经选择了父节点 并且从其后继之一中删除了选择时 节点颜色将发生变化
  • 在 Google App-Engine JAVA 中将文本转换为字符串,反之亦然

    如何从字符串转换为文本 java lang String to com google appengine api datastore Text 反之亦然 Check Javadoc http code google com appengin
  • 如何重新启动死线程? [复制]

    这个问题在这里已经有答案了 有哪些不同的可能性可以带来死线程回到可运行状态 如果您查看线程生命周期图像 就会发现一旦线程终止 您就无法返回到新位置 So 没有办法将死线程恢复到可运行状态 相反 您应该创建一个新的 Thread 实例
  • 在浏览器刷新中刷新检票面板

    我正在开发一个付费角色系统 一旦用户刷新浏览器 我就需要刷新该页面中可用的统计信息 统计信息应该从数据库中获取并显示 但现在它不能正常工作 因为在页面刷新中 java代码不会被调用 而是使用以前的数据加载缓存的页面 我尝试添加以下代码来修复
  • Spring表单ModelAttribute字段验证避免400 Bad Request错误

    我有一个ArticleFormModel包含正常发送的数据html form由 Spring 使用注入 ModelAttribute注释 即 RequestMapping value edit method RequestMethod PO

随机推荐

  • 芯片后端开发基础知识(二)

    目录 1 静态时序分析 Static Timing Analysis 2 波形的压摆 Slew 3 信号偏斜 Skew 4 时序路径 Clock Path 5 时序弧 Timing Arc 6 时钟域 Clock Domain 7 工作环境
  • 【IPC-UNIX网络编程】第4章管道和FIFO

    1 一个简单的客户 服务器例子 Client从标准输入 stdin 读进一个路径名 并把它写入IPC通道 Server从该IPC通道读出这个路径名 并尝试打开其文件 若server能打开该文件 它能读出其中的内容 并写入 不一定同一个 IP
  • 本科毕设——基于人脸识别的签到系统的研究

    本人普通四非本科 毕设选了这个比较大众且成熟的选题 四处借鉴后完成了论文 现在写写一些我完成毕设期间的历程 在完成论文开题报告后我开始寻求代码以期完成一个简易人脸识别签到系统的设计 开始我用了舍友选修课人工智能的大作业 他所采用的是传统的h
  • Adapter模式——设计模式学习笔记

    Adapter模式 一 意图 将一个类的接口转换成客户希望的另外一个接口 Adapter模式使得原本由于接口不兼容而不能在一起工作的那些类可以在一起工作 二 动机 为复用而设计的通用的类 总是存在一些特殊的情况 使其不能够使用或者完成相应的
  • pt工具常用命令

    pt工具介绍 Percona Toolkit简称pt工具 是Percona公司开发用于管理MySQL的工具 功能包括检查主从复制的数据一致性 检查重复索引 定位IO占用高的表文件 在线DDL等 DBA熟悉掌握后将极大提高工作效率 下载地址h
  • YOLO物体检测-系列教程2:YOLOV2整体解读

    YOLO 系列教程 总目录 YOLOV1整体解读 YOLOV2整体解读 YOLOV2提出论文 YOLO9000 Better Faster Stronger 1 YOLOV1 优点 快速 简单 问题1 每个Cell只预测一个类别 如果重叠无
  • 第二十七课、应用程序中的主窗口------------------狄泰软件学院

    一 主窗口的概念 1 应用程序中的主窗口 1 主窗口是与用户进行长时间交互的顶级窗口 2 程序的绝大多数功能直接由主窗口提供 3 主窗口通常是应用程序启动后显示的第一个窗口 4 整个程序由一个主窗口和多个对话框组成 2 Qt中的主窗口 1
  • leetcode排序算法总结—时间复杂度o(nlogn)-希尔/堆排/快排/归并小记

    排序算法总结 时间复杂度O nlogn 希尔 堆排序 快排 归并 希尔排序 有一段间隔的排序 可以逐个子表进行排序 然 例如王道 都给出便于计算机进行连续访问的程序算法 即依次按元素比较不同子表进行子表的调整 时间复杂度O n 1 3 最坏
  • 面向对象设计原则——开闭原则

    开闭原则是面向对象的可复用设计的第一块基石 它是最重要的面向对象设计原则 开闭原则由Bertrand Meyer于1988年提出 定义 开闭原则 Open Closed Principle OCP 一个软件实体应当对扩展开放 对修改关闭 即
  • 盘点2013:21款最优秀的开源数据库

    作为一名软件开发人员或DBA 其中一份必不可少的工作就是与数据库打交道 比如MS SQL服务器 MySQL Oracle PostgreSQL MongoDB等等 众所周知 其中MySQL是目前使用最广泛最好的免费开源数据库 此外 还有一些
  • C++11新特性——互斥锁、条件变量、原子类型

    1 互斥锁 C 11提供了四种互斥锁 mutex 互斥锁 timed mutex 带超时机制的互斥锁 recursive mutex 递归互斥锁 recursive timed mutex 带超时机制的递归互斥锁 包含头文件 include
  • http和Tcp的长连接和短连接

    转自 https www cnblogs com fubaizhaizhuren p 7523374 html http协议和tcp ip 协议的关系 1 http是应用层协议 tcp协议是传输层协议 ip协议是网络协议 2 IP协议主要解
  • Blender学习笔记(1)快捷键

    鼠标中键 转动视角 shift 中键 平移视角 ctrl 中键上下移动 缩放画面 shift 左键 多选 a是全选 b是多选 在编辑模式下是挤出 ctrl 右键 套索工具 ctrl shift 右键 diselect 中间滚轮滚动 缩放画面
  • Qt Creator 常见问题记录

    1 资源文件不显示 由于不小心删除了工程目录中的qrc文件 重新加回去后 发现项目树中Resources不见了 如下图 图中是显示的 解决办法 选择项目右键 清除 再重新缩放项目 即可看到 2 多个项目 如何选择某个项目作为启动项 VS中可
  • C++ SFINAE简介和std::enable_if_t的简单使用

    最近整理代码时发现了有人常会使用std enable if t 据说这个是C 14才支持的写法 因此再次勾起了我的整理欲 但要是熟悉std enable if的话其实也没啥太大难度 自认为这种使用方式主要提供了一种通过模板偏特化来实现的类型
  • 字符设备驱动相关函数

    Linux内核中 a 使用cdev结构体来描述字符设备 b 通过其成员dev t来定义设备号 分为主 次设备号 以确定字符设备的唯一性 c 通过其成员file operations来定义字符设备驱动提供给VFS的接口函数 如常见的open
  • ubuntu 与 windows terminal zsh 美化教程

    ubuntu 与 windows terminal zsh 美化教程 安装 zsh 和 oh my zsh 选择与安装主题 使用自带的主题 安装 powerlevel10k 主题 1 下载 p10k 主题 2 下载 Meslo LG M R
  • io使用率高运行堵塞怎么解决?linux系统由io使用率高引起的运行堵塞的解决方法

    1 在宝塔查看服务器负载100 而cpu和内存使用率都正常 输入top命令查看平均负载 查看结果负载果然很高 2 接着查看io使用情况 使用iotop工具 安装 yum install iotop 运行命令 iotop 如果安装不上是因为i
  • 实体类(VO,DO,DTO)的划分

    经常会接触到VO DO DTO的概念 本文从领域建模中的实体划分和项目中的实际应用情况两个角度 对这几个概念进行简析 得出的主要结论是 在项目应用中 VO对应于页面上需要显示的数据 表单 DO对应于数据库中存储的数据 数据表 DTO对应于除
  • Spring学习笔记2:注解开发、AOP思想、整合Mybatis、事务

    文章目录 7 使用注解开发 7 1 属性如何注入 1 Component 2 Value 7 2 衍生的注解 7 3 自动装配 7 4 作用域 1 Scope singleton 7 5 小结 9 使用java的方式配置Spring 9 1