Spring基础

一. IOC(控制反转)

  • Spring中的IOC是通过工厂模式进行解耦。先把对象都使用配置文件配置起来,当启动服务器应用加载的时候, 让一个类中的方法通过读取配置文件,把这些对象创建出来并存起来。在接下来的使用的时候,直接拿过来用就好了。Spring采用的是Map这种数据结构存储对象。

1. 基于xml的IOC配置

1.1 基本配置

1.1.1 SpringIOC所要使用的maven坐标:
<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.0.2.RELEASE</version></dependency>
</dependencies>
1.1.2 Spring的xml的配置
<!--把对象的创建交给spring来管理-->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsd"><!--把对象的创建交给spring来管理 Map结构:key为id,value为class--><bean id="accountService" class="com.iteima.service.implAccountServiceImpl"></bean><bean id="accountDao" class="com.iteima.dao.impl.AccountDaoImpl"></bean>
</beans>
1.1.3 Java代码的使用

在这里插入图片描述

  • BeanFactory才是Application的顶层接口。
  • ApplicationContext是它的子接口。
  • BeanFactory 和 ApplicationContext 的区别:创建对象的时间点不一样
    • ApplicationContext:它在构建核心容器时,创建对象采取的策略是采用立即加载的方式。也就是说,只要一读取配置文件马上就创建配置文件中配置的对象。适用单例对象
    • BeanFactory:它在构建核心容器时,创建对象采取的策略是采用延迟加载的方式。也就是说,什么时候根据id获取对象了,什么时候才真正的创建对象。适用多例对象
/**
* ApplicationContext的三个常用实现类:
*       ClassPathXmlApplicationContext: 它可以加载类路径的配置文件,要求配置文件必须在类路径下。不在的话,加载不了(更常用)
*       FileSystemXmlApplicationContext: 它可以加载磁盘意路径下的配置文件(必须有访问权限)
*       AnnotationConfigApplicationContext: 他是用于读取注解创建容器的。
*/
public static void main(String[] args){//1. 获取核心容器对象ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");//2. 根据id获取Bean对象: 两种方式IAccountService accountService = (IAccountService) applicationContext.getBean("accountService");IAccountDao accountDao = applicationContext.getBean("accountDao", IAccountDao.class);
}

1.2 IOC中bean标签

1.2.1 创建bean的三种方式
  • 第一种方式: 使用默认构造函数创建
    • 在spring的配置文件中使用bean标签,配以id和class属性之后,且没有其他属性和标签时。
    • 采用的就是默认构造创建bean对象,此时如果类中没有默认构造函数,则对象无法创建。
<bean id="accountService" class="com.iteima.service.impl.AccountServiceImpl"></bean>
  • 第二种方式: 使用普通工厂中的方法创建对象(使用某个类中的方法创建对象,并存入spring容器)
<bean id="instanceFactory" class="com.iteima.factory.InstanceFactory"></bean>
<bean id="accountService" factory-bean="instanceFactory" factory-method="getAccountService"></bean>
/*
* 模拟一个工厂类(该类可能是存在于jar包中的,我们无法通过修改源码的方式来提供默认的构造函数)
* */
public class InstanceFactory {public IAccountService getAccountService() {return new AccountServiceImpl();}
}
  • 第三种方式: 使用工厂中的静态方法创建对象(使用某个类中的静态方法创建对象,并存入spring容器)
<bean id="accountService" class="com.iteima.factory.StaticFactory" factory-method="getAccountService"></bean>
public class StaticFactory {public static IAccountService getAccountService() {return new AccountServiceImpl();}
}
1.2.2 bean的作用范围
  • bean标签的scope属性: 作用:用于指定bean的范围,scope的取值:
    • singleton: 单例的(默认值)
    • prototype: 多例的
    • request:作用于web应用的请求范围
    • session:作用于web应用的会话范围
    • global-session:作用于集群环境的会话范围(全局会话范围),当不是集群环境时,它就是session
  • init-method: 指定类中的初始化方法名称。
  • destroy-method: 指定类中销毁方法名称。
1.2.3 bean对象的生命周期
  • 单例对象:
    • 出生:当容器创建时对象出生
    • 活着:只要容器还在,对象一直活着
    • 死亡:容器销毁,对象消亡
    • 总结:单例对象的生命周期和容器相同
  • 多例对象:
    • 出生:当我们使用对象时spring框架为我们创建
    • 活着:对象只要是在使用过程中就一直活着
    • 死亡:当对象长时间不用,且没有别的对象引用时,由Java的垃圾回收器回收,Spring框架不负责销毁

1.3 DI(依赖注入)

  • 依赖注入能注入的数据:有三类
    • 基本类型和String
    • 其他bean类型(在配置文件中或者注解配置过的bean)
    • 复杂类型/集合类型
  • 注入的方式:有三种
    • 第一种:使用构造函数提供
    • 第二种:使用set方法提供
    • 第三种:使用注解提供
1.3.1 构造函数注入
<!-- 构造函数注入:使用的标签:constructor-arg标签出现的位置:bean标签的内部标签中的属性type: 用于指定要注入的数据的数据类型,该数据类型也是构造函数中某个或某些参数的类型index:用于指定要注入的数据给构造函数中指定索引位置的参数赋值。索引的位置是从0开始name:用于指定给构造函数中指定名称的参数赋值   常用的==============以上三个用于指定给构造函数中哪个参数赋值================value: 用于提供基本类型和String类型的数据ref:用于指定其他的bean类型数据。它指的就是在spring的IOC核心容器中出现过的bean对象优势:在获取bean对象时,注入数据是必须的操作,否则对象无法创建成功弊端:改变了bean对象的实例化方式,使我们在创建对象时,如果用不到这些数据,也必须提供
-->
<bean id="accountService" class="com.iteima.service.impl.AccountServiceImpl"><constructor-arg name="name" value="test"></constructor-arg><constructor-arg name="age" value="18"></constructor-arg><constructor-arg name="birthday" ref="now"></constructor-arg>
</bean>
<!-- 配置一个日期对象 -->
<bean id="now" class="java.util.Date"></bean>
public class AccountServiceImpl implements IAccountService {//如果是经常变化的数据,并不适用与注入的方式private String name;private Integer age;private Date birthday;public AccountServiceImpl(String name, Integer age, Date birthday) {this.name = name;this.age = age;this.birthday = birthday;}
}
1.3.2 set方法注入(更常用)
<!-- set方法注入涉及的标签:property出现的位置:bean标签的内部标签的属性:name:用于指定注入时所调用的set方法名称value: 用于提供基本类型和String类型的数据ref:用于指定其他的bean类型数据。它指的就是在spring的IOC核心容器中出现过的bean对象优势:创建对象时没有明确的限制,可以直接使用默认构造函数弊端:如果某个成员必须有值,则获取对象是有可能set方法没有执行
-->
<bean id="accountService2" class="com.iteima.service.impl.AccountServiceImpl2"><property name="name" value="TEST"></property><property name="age" value="21"></property><property name="birthday" ref="now"></property>
</bean>
<!-- 配置一个日期对象 -->
<bean id="now" class="java.util.Date"></bean>
public class AccountServiceImpl2 implements IAccountService {private String name;private Integer age;private Date birthday;public void setName(String name) {this.name = name;}public void setAge(Integer age) {this.age = age;}public void setBirthday(Date birthday) {this.birthday = birthday;}
}
1.3.3 使用p名称空间注入数据(本质还是调用set方法)
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:p="http://www.springframework.org/schema/p"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation=" http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="accountService"class="com.itheima.service.impl.AccountServiceImpl4"p:name="test" p:age="21" p:birthday-ref="now"/><!-- 配置一个日期对象 --><bean id="now" class="java.util.Date"></bean>
</beans>
1.3.4 注入集合属性
  • 用于给List结构集合注入的标签:
    • list array set: 这三个标签可以互换使用
  • 用于给Map结构集合注入的标签:
    • map props:这两个标签可以互换使用
<bean id="accountService3" class="com.iteima.service.impl.AccountService><property name="myStrs"><array><value>AAA</value><value>BBB</value><value>CCC</value></array></property><property name="myList"><list><value>AAA</value><value>BBB</value><value>CCC</value></list></property><property name="mySet"><set><value>AAA</value><value>BBB</value><value>CCC</value></set></property><property name="myMap"><map><entry key="testA" value="aaa"></entry><entry key="testB"><value>BBB</value></entry></map></property><property name="myProps"><props><prop key="testC">ccc</prop><prop key="testD">ddd</prop></props></property>
</bean>
public class AccountServiceImpl3 implements IAccountService {private String[] myStrs;private List<String> myList;private Set<String> mySet;private Map<String,String> myMap;private Properties myProps;public void setMyStrs(String[] myStrs) {this.myStrs = myStrs;}public void setMyList(List<String> myList) {this.myList = myList;}public void setMySet(Set<String> mySet) {this.mySet = mySet;}public void setMyMap(Map<String, String> myMap) {this.myMap = myMap;}public void setMyProps(Properties myProps) {this.myProps = myProps;}
}

2. 基于注解的IOC配置

2.1 用于创建对象的注解

  • 他们的作用就和在XML配置文件中编写一个<bean>标签实现的功能是一样的。
  • @Component: 用于把当前类对象存入spring容器中
    • 属性:value:用于指定bean的id。当我们不写时,它的默认值是当前类名,且首字母改小写。
  • @Controller: 一般用在表现层
  • @Service: 一般用在业务层
  • @Repository: 一般用在持久层

小总结:
以上三个注解他们的作用和属性与component属性是一模一样的。
他们三个是spring框架为我们提供明确的三层使用的注解,使我们的三层对象更加清晰

2.2 用于注入数据的注解

  • 他们的作用就和在xml配置文件中的bean标签中写一个标签的作用是一样的。
  • @Autowired: 自动按照类型注入,只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配,就可以注入成功。
    • 如果ioc容器中没有任何bean的类型和要注入的变量类型匹配,则报错
    • 如果ioc容器中有多个类型匹配时:按照变量名找到与bean中匹配的id
    • 在使用注解时,set方法就不是必须的了
  • @Qualifier: 在按照类中注入的基础之上再按照名称注入。它在给类成员注入时不能单独使用。但是在给方法参数注入时可以
@Autowired
@Qualifier("accountDao1")
private IAccountDao accountDao;
  • @Resource: 直接bean的id注入。它可以独立使用
    • 属性:name: 用于指定bean的id
@Resource(name = "accountDao1")
private IAccountDao accountDao;
  • @Value: 用于注入基本类型和String类型的数据
    • 属性:value:用于指定数据的值。它可以使用spring中SpEL(spring中的el表达式),SpEL的写法:${表达式}

小总结:
@Autowired,@Qualifier,@Resource: 三个注解只能注入其他bean类型的数据,而基本类型和String类型无法使用上述注解实现
另外集合类型的注入只能通过XML来实现

2.3 用于改变作用范围的

  • 他们的作用就和在bean标签中使用scope属性实现的功能是一样的
  • @Scope: 用于指定bean的作用范围。
    • 属性:value:指定范围的取值。常用取值:singleton prototype
@Component("accountService")
@Scope("prototype")
public class AccountServiceImpl{}

2.4 生命周期相关的注解(了解)

  • 他们的作用就和在bean标签中init-method和destroy-method的作用是一样的。
  • @PreDestroy: 用于指定销毁方法
  • @PostConstruct: 用于指定初始化方法

2.5 配置相关的注解

  • @Configuration: 指定当前类是一个配置类

    • 当配置类作为AnnotationConfigApplicationContext对象创建的参数时,该注解可以不写
  • @ComponentScan: 指定通过注解指定spring在创建容器时要扫描的包

    • 属性:value:它和basePackages的作用是一样的,都是用于指定创建容器时要扫描的包
    • 与下面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:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsd"><!-- 告知spring在创建容器时要扫描的包,配置所需要的标签不是在beans的约束中,而是一个名称为context名称空间和约束中--><context:component-scan base-package="com.iteima"></context:component-scan>
    </beans>
    
  • @Bean: 用于把当前方法的返回值作为bean对象存入spring的IOC容器中

    • 属性:name:用于指定bean的id,默认值是当前方法的名称
    • 细节:当我们使用注解配置方法时,如果方法有参数,spring框架会去容器中查找有没有可用的bean对象。查找的方式和Autowired注解的作用是一样的。
@Bean("runner")
public QueryRunner createQueryRunner(@Qualifier("dataSource") DataSource dataSource) {return new QueryRunner(dataSource);
}
  • @Import: 用于导入其他的配置类

    • 属性:value:用于指定其他配置类的字节码
    • 当我们使用Import的注解之后,有Import注解的类就是父配置类,而导入的都是子配置类
  • @PropertySource: 作用:用于指定properties文件的位置

    • 属性:value:指定文件名称和路径
    • 关键字:classpath:表示类路径下
  • 小总结:

@Configuration
@ComponentScan("com.iteima")
@Import(JdbcConfig.class)
@PropertySource("classpath:jdbcConfig.properties")
public class SpringConfiguration {}

3. Spring整合Junit

  • 1.导入相应的maven坐标
<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.0.2.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.0.2.RELEASE</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency>
</dependencies>
  • 2.编写测试类
    • @ContextConfiguration:
      • locations: 指定xml文件的位置,加上classpath关键字,表示在类路径下
      • classes:指定注解类所在地位置
    • 当我们使用spring 5.x版本的时候,要求junit的jar必须是4.12及以上
    • 我们测试时便不用写实例化ApplicationContext了。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration.class) //没有xml文件的情况,使用@Configuration注解的情况
//@ContextConfiguration(locations = "classpath:bean.xml") 有xml文件的情况
public class AccountServiceTest {@Autowiredprivate IAccountService accountService;
}

二. AOP(面向切面编程)

  • AOP是把我们程序重复的代码抽取出来,在需要执行的时候,使用动态代理的技术,在不修改源码的基础上,对我们的已有方法进行增强。

1. 动态代理

1.1 基于接口的动态代理

public class Client {public static void main(String[] args){//Producer是实体类final Producer producer = new Producer();/** 动态代理:*   特点:字节码随用随加载*   作用:不修改源码的基础上对方法增强*   分类:*       基于接口的动态代理*       基于子类的动态代理*   基于接口的动态代理:*       涉及的类:Proxy*       提供者:JDK官方*   如何创建代理对象:*       使用Proxy类中的newProxyInstance方法*   创建代理对象的要求:*       被代理类最少实现一个接口,如果没有则不能使用*    newProxyInstance方法的参数:*       ClassLoader:类加载器*           他是用于加载代理对象字节码的。和被代理对象使用相同的类加载器。固定写法*       Class[]:字节码数组*           它是用于让代理对象和被代理对象有相同方法。固定写法*       InvocationHandler:用于提供增强的代码*           他是让我们写如何代理。我们一般都是写一些该接口的实现类。通常情况下都是匿名内部类,但不是必须的。*           此接口的实现类都是谁用谁写。* *///此时不实现接口不能使用//IProducer是接口IProducer proxyProducer = (IProducer) Proxy.newProxyInstance(producer.getClass().getClassLoader(),producer.getClass().getInterfaces(), new InvocationHandler() {/*** 作用:执行被代理对象的任何借口方法都会经过该方法* 方法参数的含义* @param proxy 代理对象的引用* @param method 当前执行的方法* @param args 当前执行方法所需的参数* @return 和被代理对象有相同的返回值* @throws Throwable*/public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//提供增强的代码Object returnValue = null;//1. 获取方法执行的参数Float money = (Float)args[0];//2. 判断当前方法是不是销售if("saleProduct".equals(method.getName())) {returnValue = method.invoke(producer, money * 0.8f);}return returnValue;}});proxyProducer.saleProduct(10000f);}
}

1.2 基于子类的动态代理

  • 1.导入相应的jar包
<dependencies><dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>2.1_3</version></dependency>
</dependencies>
  • 2.java代码:
public class Client {public static void main(String[] args){final Producer producer = new Producer();/** 动态代理:*   特点:字节码随用随加载*   作用:不修改源码的基础上对方法增强*   分类:*       基于接口的动态代理*       基于子类的动态代理*   基于子类的动态代理:*       涉及的类:Enhancer*       提供者:第三方cglib库*   如何创建代理对象:*       使用Enhancer类中的create方法*   创建代理对象的要求:*       被代理类不能是最终类*    create方法的参数:*       Class:字节码*           它是用于指定被代理对象的字节码*       Callback:用于提供增强的代码*           他是让我们写如何代理。我们一般都是写一些该接口的实现类。通常情况下都是匿名内部类,但不是必须的。*           此接口的实现类都是谁用谁写。*           我们一般写的都是该接口的子接口实现类:MethodInterceptor* *///没有实现任何接口Producer cglibProducer = (Producer) Enhancer.create(producer.getClass(), new MethodInterceptor() {/*** 执行被代理对象的任何方法都会经过该方法* @param proxy* @param method* @param args*  以上三个参数和基于接口的动态代理中invoke方法的参数是一样的* @param methodProxy:当前执行方法的代理对象* @return* @throws Throwable*/public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {//提供增强的代码Object returnValue = null;//1. 获取方法执行的参数Float money = (Float)args[0];//2. 判断当前方法是不是销售if("saleProduct".equals(method.getName())) {returnValue = method.invoke(producer, money * 0.8f);}return returnValue;}});cglibProducer.saleProduct(12000f);}
}

2. AOP相关术语

  • Joinpoint(连接点): 所谓连接点是指那些被拦截到的点。在 spring 中,这些点指的是方法,因为 spring 只支持方法类型的
    连接点。
  • Pointcut(切入点): 所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义。
  • Advice(通知/增强): 所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知。通知的类型: 前置通知,后置通知,异常通知,最终通知,环绕通知。
  • Introduction(引介): 引介是一种特殊的通知在不修改类代码的前提下, Introduction 可以在运行期为类动态地添加一些方
    法或 Field。
  • Target(目标对象): 代理的目标对象。
  • Weaving(织入): 是指把增强应用到目标对象来创建新的代理对象的过程。spring 采用动态代理织入,而 AspectJ 采用编译期织入和类装载期织入。
  • Proxy(代理): 一个类被 AOP 织入增强后,就产生一个结果代理类。
  • Aspect(切面): 是切入点和通知(引介)的结合。

3. AOP的xml配置

3.1 导入相应的maven依赖

<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.7</version>
</dependency>

3.2 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/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsd"><!--配置spring的IOC,把service对象配置进来--><bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"></bean><!--spring中基于XML的AOP配置步骤1. 把通知Bean也交给spring来管理2. 使用aop:config标签表明开始AOP的配置3. 使用aop:aspect标签表明配置切面id属性:是给切面提供一个唯一标识ref属性:是指定通知类bean的Id4. 在aop:aspect标签的内部使用对应标签来配置通知的类型我们现在示例是让printLog方法在切入点方法执行之前:所以是前置通知aop:before:表示配置前置通知method属性:用于指定Logger类中哪个方法是前置通知pointcut属性:用于指定切入点表达式,该表达式的含义指的是对业务中哪些方法增强切入点表达式的写法:关键字:execution(表达式)表达式:访问修饰符 返回值 包名.包名.包名.....类名.方法名(参数列表)标准的表达式写法:public void com.itheima.service.impl.AccountServiceImpl.saveAccount()访问修饰符可以省略void com.itheima.service.impl.AccountServiceImpl.saveAccount()返回值可以使用通配符,表示任意返回值* com.itheima.service.impl.AccountServiceImpl.saveAccount()包名可以使用通配符,表示任意包。但是有几级包,就需要写几个*.* *.*.*.*.AccountServiceImpl.saveAccount()包名可以使用..表示当前包及其子包* *..AccountServiceImpl.saveAccount()类名和方法名都可以使用*来实现通配参数列表:可以直接写数据类型:基本数据类型直接名称引用类型写包名.类名的方式 java.lang.String可以使用通配符表示任意类型,但是必须有参数可以使用..表示有无参数均可,有参数可以是任意类型全通配写法:* *..*.*(..)实际开发中切入点表达式的通常写法:切到业务层实现类下的所有写法* com.itheima.service.impl.*.*(..)--><!--配置Logger类 --><bean id="logger" class="com.itheima.utils.Logger"></bean><!--配置AOP--><aop:config><!--配置切面--><aop:aspect id="logAdvice" ref="logger"><!--配置通知的类型,并且建立通知方法和切入点方法的关联--><aop:before method="printLog" pointcut="execution(* com.itheima.service.impl.*.*(..))"></aop:before></aop:aspect></aop:config>
</beans>
<!--配置AOP-->
<aop:config><!-- 配置切入点表达式 id属性用于指定表达式的唯一标识。expression属性用于指定表达式内容此标签写在aop: aspect标签内部只能当前切面使用。它还可以写在aop: aspect外面,此时就变成了所有切面可用--><aop:pointcut id="pt1" expression="execution(* com.itheima.service.impl.*.*(..))"></aop:pointcut><!--配置切面--><aop:aspect id="logAdvice" ref="logger"><!--配置前置通知: 在切入点方法执行之前执行--><aop:before method="beforePrintLog" pointcut-ref="pt1"></aop:before><!--配置后置通知:在切入点方法正常执行之后执行。它和异常通知只能执行一个。--><aop:after-returning method="afterReturningPrintLog" pointcut-ref="pt1"></aop:after-returning><!--配置异常通知:在切入点方法执行产生异常之后执行。它和后置通知只能执行一个。--><aop:after-throwing method="afterThrowingPrintLog" pointcut-ref="pt1"></aop:after-throwing><!--配置最终通知:无论切入点方法是否正常执行它都会在其后面执行--><aop:after method="afterPrintLog" pointcut-ref="pt1"></aop:after><!--配置环绕通知, 详细的注释请看Logger类中--><aop:around method="aroundPrintLog" pointcut-ref="pt1"></aop:around></aop:aspect>
</aop:config>
public class Logger {/** 环绕通知* 问题:*       当我们配置了环绕通知之后,切入点方法没有执行,而通知方法执行了。* 分析:*       通过对比动态代理中的环绕通知代码:发现动态代理的环绕通知有明确的切入点方法调用,而我们的代码中没有。* 解决:*       Spring框架为我们提供了一个接口:ProceedingJoinPoint。该接口有一个方法proceed(),此方法就想相当于明确调用切入点方法。*       该接口可以作为环绕通知的方法参数:在程序执行时,spring框架会为我们提供该接口的实现类供我们使用。* spring中的环绕通知:*       它是spring框架为我们提供的一种可以在代码中手动控制增强方法何时执行的方式。* */public Object  aroundPrintLog(ProceedingJoinPoint joinPoint) {Object rtValue = null;try {Object[] args = joinPoint.getArgs(); //得到方法执行所需的参数System.out.println("Logger类中的aroundPrintLog方法开始记录日志了。。前置");rtValue = joinPoint.proceed(); //明确调用业务层方法(切入点方法)System.out.println("Logger类中的aroundPrintLog方法开始记录日志了。。后置");return rtValue;} catch (Throwable throwable) {System.out.println("Logger类中的aroundPrintLog方法开始记录日志了。。异常");throw new RuntimeException(throwable);} finally {System.out.println("Logger类中的aroundPrintLog方法开始记录日志了。。最终");}}
}

4. AOP的注解配置

4.1 java代码示例

/*
* 使用注解配置AOP时,后置通知或者异常通知会在最终通知之后执行。
*
* */
@Component("logger")
@Aspect //表示当前类是一个切面类
public class Logger {@Pointcut("execution(* com.itheima.service.impl.*.*(..))")private void pt1(){}/** 前置通知* */@Before("pt1()")public void beforePrintLog() {System.out.println("前置通知Logger类中的beforePrintLog方法开始记录日志了");}/** 后置通知* */@AfterReturning("pt1()")public void afterReturningPrintLog() {System.out.println("后置通知Logger类中的afterReturningPrintLog方法开始记录日志了");}/** 异常通知* */@AfterThrowing("pt1()")public void afterThrowingPrintLog() {System.out.println("异常通知Logger类中的afterThrowingPrintLog方法开始记录日志了");}/** 最终通知* */@After("pt1()")public void afterPrintLog() {System.out.println("最终通知Logger类中的afterPrintLog方法开始记录日志了");}/** 环绕通知* 问题:*       当我们配置了环绕通知之后,切入点方法没有执行,而通知方法执行了。* 分析:*       通过对比动态代理中的环绕通知代码:发现动态代理的环绕通知有明确的切入点方法调用,而我们的代码中没有。* 解决:*       Spring框架为我们提供了一个接口:ProceedingJoinPoint。该接口有一个方法proceed(),此方法就想相当于明确调用切入点方法。*       该接口可以作为环绕通知的方法参数:在程序执行时,spring框架会为我们提供该接口的实现类供我们使用。* spring中的环绕通知:*       它是spring框架为我们提供的一种可以在代码中手动控制增强方法何时执行的方式。* */@Around("pt1()")public Object  aroundPrintLog(ProceedingJoinPoint joinPoint) {Object rtValue = null;try {Object[] args = joinPoint.getArgs(); //得到方法执行所需的参数System.out.println("Logger类中的aroundPrintLog方法开始记录日志了。。前置");rtValue = joinPoint.proceed(); //明确调用业务层方法(切入点方法)System.out.println("Logger类中的aroundPrintLog方法开始记录日志了。。后置");return rtValue;} catch (Throwable throwable) {System.out.println("Logger类中的aroundPrintLog方法开始记录日志了。。异常");throw new RuntimeException(throwable);} finally {System.out.println("Logger类中的aroundPrintLog方法开始记录日志了。。最终");}}
}
  • 注意:当使用注解aop时,最终通知会发生在后置通知或者异常通知之前。环绕通知则不会出现这种情况。

4.2 xml开启注解AOP支持

<?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"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsd"><!--配置spring创建容器时要扫描的包--><context:component-scan base-package="com.itheima"></context:component-scan><!--配置spring开启注解AOP的支持--><aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
  • @EnableAspectJAutoProxy:该注解可以开启AOP的支持,与<aop:aspectj-autoproxy></aop:aspectj-autoproxy>作用一样。

三. Spring的事务控制

1. 事务控制的API

1.1 PlatformTransactionManager接口

  • 该接口提供事务操作的方法:

    • 获取事务状态信息:TransactionStatus getTransaction(TransactionDefinition definition)
    • 提交事务:void commit(TransactionStatus status)
    • 回滚事务:void rollback(TransactionStatus status)
  • 该接口的实现类:

    • org.springframework.jdbc.datasource.DataSourceTransactionManager:使用 SpringJDBC 或 iBatis 进行持久化数据时使用
    • org.springframework.orm.hibernate5.HibernateTransactionManager:使用Hibernate 版本进行持久化数据时使用

1.2 TransactionDefinition

  • 它是事务的定义信息对象:
    • String getName():获取事务对象名称
    • int getIsolationLevel():获取事务隔离级别
    • int getPropagationBehavior():获取事务传播行为
    • int getTimeout():获取事务超时时间
    • boolean isReadOnly():获取事务是否只读

1.3 TransactionStatus

  • 此接口提供的是事务具体的运行状态:
    • void flush():刷新事务
    • boolean hasSavepoint():获取是否存在存储点(可以设置事务回滚到的位置)
    • boolean isCompleted():获取事务是否完成
    • boolean isNewTransaction():获取事务是否为新事务
    • boolean isRollbackOnly():获取事务是否回滚

2. 事务的相关概述

2.1 事务的隔离级别

  • 事务隔离级反映事务提交并发访问时的处理态度
  • ISOLATION_DEFAULT:默认级别:ISOLATION_REPEATABLE_READ
  • ISOLATION_READ_UNCOMMITTED:可以读取未提交的数据
  • ISOLATION_READ_COMMITTED:只能读取已提交数据,解决脏读问题(Oracle默认级别)
  • ISOLATION_REPEATABLE_READ:是否读取其他事务提交修改后的数据,解决不可重复读问题(MySql默认级别)
  • ISOLATION_SERIALIZABLE:是否读取其他事务提交添加后的数据,解决幻读问题

2.2 事务的传播行为

  • REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。一般的选择(默认值)
  • SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行(没有事务)
  • MANDATORY: 使用当前的事务,如果当前没有事务,就抛出异常
  • REQUERS_NEW: 新建事务,如果当前在事务中,把当前事务挂起
  • NOT_SUPPORTED: 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
  • NEVER: 以非事务方式运行,如果当前存在事务,抛出异常
  • NESTED: 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行 REQUIRED 类似的操作

3. 事务的xml配置

3.1 导入相应的maven依赖

<dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>5.0.2.RELEASE</version>
</dependency>

3.2 xml的配置编写

  • spring中基于xml的声明式事务控制配置步骤;
    1. 配置事务管理器
    2. 配置事务的通知
    3. 配置AOP中的通用切入点表达式
    4. 建立事务通知和切入点表达式的对应关系
    5. 配置事务的属性
<?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"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/txhttps://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsd"><!--配置账户的持久层--><bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl"><property name="dataSource" ref="dataSource"></property></bean><!-- 配置业务层 --><bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"><property name="accountDao" ref="accountDao"></property></bean><!--配置数据源--><bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"></property><property name="url" value="jdbc:mysql://localhost:3306/eesy"></property><property name="username" value="root"></property><property name="password" value=""></property></bean><!--spring中基于xml的声明式事务控制配置步骤1. 配置事务管理器2. 配置事务的通知此时我们需要导入事务的约束 tx名称空间约束,同时也需要aop使用tx:advice标签配置事务通知属性:id: 给事务通知起一个唯一标识transaction-manager:给事务通知提供一个事务管理器引用3. 配置AOP中的通用切入点表达式4. 建立事务通知和切入点表达式的对应关系5. 配置事务的属性是在事务的通知tx:advice标签的内部--><!--1. 配置事务管理器--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property></bean><!--2. 配置事务的通知 --><tx:advice id="txAdvice" transaction-manager="transactionManager"><!--5. 配置事务的属性isolation=""  用于指定事务的隔离级别。默认值是DEFAULT,表示使用数据库的默认隔离级别no-rollback-for="" 用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时事务回滚。没有默认值。不写表示任何异常都回滚。propagation="" 用于指定事务的传播行为。默认值是REQUIRED,表示一定会有事务,增删改的选择。查询方法可以选择SUPPORTS.read-only="" 用于指定事务是否只读。只有查询方法才能设置为true。默认值是false,表示读写rollback-for="" 用于指定一个异常,当产生该异常时,事务回滚,产生其他异常时,事务不回滚。没有默认值。表示任何异常都回滚。timeout="" 用于指定事务的超时时间,默认值是-1,表示永不超时。如果指定了数值,以秒为单位--><tx:attributes><!-- *(通配符)表示:所有方法 --><tx:method name="*" propagation="REQUIRED" read-only="false"/><!-- find*表示:以find开头的所有方法 --><tx:method name="find*" propagation="SUPPORTS" read-only="true"></tx:method></tx:attributes></tx:advice><!--配置AOP--><aop:config><!--3. 配置切入点表达式--><aop:pointcut id="pt1" expression="execution(* com.itheima.service.impl.*.*(..))"></aop:pointcut><!--4. 建立切入点表达式和事务通知的对应关系--><aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"></aop:advisor></aop:config>
</beans>

4. 事务的注解配置

4.1 java类上的注解配置

  • @Transactional: 该注解可以出现在接口上,类上和方法上
    • 出现接口上,表示该接口的所有实现类都有事务支持
    • 出现在类上,表示类中所有方法有事务支持
    • 出现在方法上,表示方法有事务支持
/*
*  账户的业务实现类
*
*  事务控制应该都是在业务层
* */
@Service("accountService")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
public class AccountServiceImpl implements IAccountService {@Autowiredprivate IAccountDao accountDao;public Account findAccountById(Integer accountId) {return accountDao.findAccountById(accountId);}//需要的是读写型事务配置@Transactional(propagation = Propagation.REQUIRED, readOnly = false)public void transfer(String sourceName, String targetName, Float money) {//1.根据名称查询转出账户Account source = accountDao.findAccountByName(sourceName);//2.根据名称查出转入账户Account target = accountDao.findAccountByName(targetName);//3.转出账户减钱source.setMoney(source.getMoney() - money);//4.转入账户加钱target.setMoney(target.getMoney() + money);//5.更新转出账户accountDao.updateAccount(source);int i = 1 / 0;//6.更新转入账户accountDao.updateAccount(target);}
}

4.2 配置文件中开启事务的支持(使用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"xmlns:tx="http://www.springframework.org/schema/tx"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/txhttps://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsd"><!--配置数据源--><bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"></property><property name="url" value="jdbc:mysql://localhost:3306/eesy"></property><property name="username" value="root"></property><property name="password" value=""></property></bean><!--spring中基于注解的声明式事务控制配置步骤1. 配置事务管理器2. 开启spring对注解事务的支持3. 在需要事务支持的地方使用@Transactional注解--><!--配置事务管理器--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property></bean><!--开启spring对注解事务的支持 @EnableTransactionManagement意思相同--><tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
</beans>

4.2 配置类中开启事务的支持(不使用xml)

  • jdbcConfig.properties
jdbc.driver = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/eesy
jdbc.username = root
jdbc.password =
  • JdbcConfig.java
/*
* 和连接数据库相关的配置类
* */
public class JdbcConfig {@Value("${jdbc.driver}")private String driver;@Value("${jdbc.url}")private String url;@Value("${jdbc.username}")private String username;@Value("${jdbc.password}")private String password;/** 创建JdbcTemplate* */@Bean(name = "jdbcTemplate")public JdbcTemplate createJdbcTemplate(DataSource dataSource) {return new JdbcTemplate(dataSource);}/** 创建数据源对象* */@Bean(name = "dataSource")public DataSource createDataSource(){DriverManagerDataSource dataSource = new DriverManagerDataSource();dataSource.setDriverClassName(driver);dataSource.setUrl(url);dataSource.setUsername(username);dataSource.setPassword(password);return dataSource;}
}
  • TransactionConfig.java
/*
* 和事务相关的配置类
* */
public class TransactionConfig {/** 用于创建事务管理器对象* */@Bean(name = "transactionManager")public PlatformTransactionManager createTransactionManager(DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}
}
  • SpringConfiguration.java
/*
* spring的配置类,相当于bean.xml
* */
@Configuration
@ComponentScan("com.itheima")
@Import({JdbcConfig.class, TransactionConfig.class})
@PropertySource(value = "jdbcConfig.properties") //连接jdbcConfig.properties文件
@EnableTransactionManagement //开启spring对注解事务的支持 <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
public class SpringConfiguration {
}* */@Bean(name = "dataSource")public DataSource createDataSource(){DriverManagerDataSource dataSource = new DriverManagerDataSource();dataSource.setDriverClassName(driver);dataSource.setUrl(url);dataSource.setUsername(username);dataSource.setPassword(password);return dataSource;}
}
  • TransactionConfig.java
/*
* 和事务相关的配置类
* */
public class TransactionConfig {/** 用于创建事务管理器对象* */@Bean(name = "transactionManager")public PlatformTransactionManager createTransactionManager(DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}
}
  • SpringConfiguration.java
/*
* spring的配置类,相当于bean.xml
* */
@Configuration
@ComponentScan("com.itheima")
@Import({JdbcConfig.class, TransactionConfig.class})
@PropertySource(value = "jdbcConfig.properties") //连接jdbcConfig.properties文件
@EnableTransactionManagement //开启spring对注解事务的支持 <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
public class SpringConfiguration {
}
查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. bugku(5,6题)

    5.眼见非实&#xff1a; 首先我们先把压缩包下载下来&#xff0c;之后我们解压&#xff0c;发现一个以docx为后缀的world文档&#xff0c;其实我们不管是用world文档打开&#xff0c;还是通过题目分析都能得出其文件有问题。首先用world文档打开后发现是乱码.。如图&#xff1…...

    2024/4/22 17:21:53
  2. 综合布线基础知识

    **综合布线是一种模块化的、灵活性极高的建筑物内或建筑群之间的信息传输通道。**通过它可使话音设备、数据设备、交换设备及各种控制设备与信息管理系统连接起来&#xff0c;同时也使这些设备与外部通信网络相连的综合布线。它还包括建筑物外部网络或电信线路的连接点与应用系…...

    2024/4/2 20:38:13
  3. 冬青看世界:“银河战舰“它叕来了,鲤鱼又将跃龙门?

    就在本月&#xff0c;A股上市公司数突破4000家&#xff0c;迎来里程碑时刻。伴随市场扩容&#xff0c;今年以来&#xff0c;千亿市值股数量也不断攀升&#xff0c;证券时报记者注意到&#xff0c;今年7月13日大盘最高点时&#xff0c;千亿市值股数量一度达到125家。尽管近期部分…...

    2024/4/27 17:13:50
  4. 从外包菜鸟到测试开发,薪资一年翻三倍

    本文为霍格沃兹测试学院优秀学员学习心得与面试经验分享。 本人本科就读于某普通院校&#xff08;很普通的那种技术示范学院&#xff09;&#xff0c;毕业后懵懂的加入了软件测试这个行业&#xff0c;至今有三年工作经验。通过在霍格沃兹测试学院的这段学习经历&#xff0c;我的…...

    2024/4/18 16:48:33
  5. CleanMyMac x2021中文版mac清理软件激活码下载

    作为一名一直使用Mac的用户&#xff0c;支持清理电脑中垃圾以及各方面管理的软件都不如Windows选择范围大。不得不为了更好的使用Mac的清理软件CleanMyMac X&#xff0c;或者干脆选择了盗版软件使用。经过简单几天使用下来&#xff0c;先说结论我认为这是一款CMM&#xff08;以…...

    2024/4/24 13:47:21
  6. IOT设备——想说爱你不容易

    IOt设备是什么 物联网[Internet of things&#xff08;IOT&#xff09;]是将物理设备、车辆、建筑物和一些其他嵌入电子设备、软件、传感器等事物与网络链接起来&#xff0c;使这些对象能够手机和交换数据的网络。 然而为大众生活带来许多边界的IOT设备一旦遭受攻击&#xff0…...

    2024/4/13 0:20:14
  7. 【方案搭建】搭建智慧工厂实时视频监控系统有哪些方式?国标平台EasyGBS及EasyCVR平台对比

    移动网络为企业管理运营提供了极大地便利&#xff0c;对于有几家或者几十家工厂的管理者来说&#xff0c;非常希望能通过一种集中方式监控管理到各个工厂。 实时了解工厂运行状况&#xff0c;随时随地的了解生产过程和和突发事件等&#xff0c;同时可以将视频可以集成在企业网…...

    2024/4/28 0:13:23
  8. wuchong/jacman

    Jacman 中文说明 Jacman is a fresh looking and responsive theme for Hexo with more features and some build-in Chinese service based on Pacman. Jacman support Hexo 3.0 now ! Demo 如何使用 Jacman 主题 Installation Install $ git clone https://github.com/w…...

    2024/4/22 23:38:42
  9. 微信域名检测拦截全析

    背景 过去的产品推广方式列如线下地推和电视广告&#xff0c;但随着网络时代的到来&#xff0c;智能机更是人手一部&#xff0c;我们有了较之更高效成本更低的推广方法。微信是大家手机必备软件&#xff0c;同样也是用户量最多&#xff0c;最活跃的社交APP&#xff0c;所以在微…...

    2024/4/30 2:19:19
  10. Linux中的三种软件安装方式及服务器基本环境搭建

    jdk安装&#xff08;rpm安装&#xff09; 1、rpm下载地址http://www.oracle.com/technetwork/java/javase/downloads/index.html 2、如果有安装openjdk 则卸载 [rootkuangshen ~]# java -version java version "1.8.0_121" Java(TM) SE Runtime Environment (buil…...

    2024/4/2 4:04:58
  11. 皮肤的屏障特性是怎么一回事儿?

    人体皮肤的厚度根据身体位置而异&#xff0c;由三个不同的基本层组成&#xff1a;皮下组织&#xff0c;真皮和表皮。富含脂肪的皮下组织附着在下面的肌肉组织上&#xff0c;为身体提供填充和绝缘作用&#xff0c;而真皮则是由在胶原蛋白和弹性蛋白纤维网状结构的葡萄糖胺聚糖和…...

    2024/4/25 17:18:05
  12. Vue祖孙组件怎么传值

    Vue祖孙组件怎么传值 先看基础 祖孙组件&#xff0c;也就是 3 层嵌套的组件。关于 vue 中父子组件之间的数据传递是通过 props 和 $emit 实现&#xff0c;参考Vue 父子组件传值。 那祖孙组件之间传值怎么实现&#xff0c;先了解下面的几个 vue 属性。 $props 当前组件接收…...

    2024/5/1 8:17:33
  13. 小米10青春版和OPPOReno4SE 哪个好

    OPPOReno4SE将选用一块6.43英寸的AMOLED屏幕&#xff0c;刷新率为90Hz&#xff0c;分辨率为1080x2400&#xff0c;屏占比超过90%&#xff0c;重量为186g&#xff0c;拥有超闪蓝、超闪黑、超闪白三种手机配色 oppoReno4se更多使用感受和评价&#xff1a;https://www.oppo.com/4s…...

    2024/4/23 17:10:41
  14. 巨头竞相跨界入场,互联网风口能把猪吹多高?

    “不好好学习&#xff0c;就回去养猪去”&#xff0c;一度是老师教育学生要认真读书的口头禅。 一直以来&#xff0c;养猪都是又脏又累还不赚钱的代名词&#xff0c;就是这样一个遭到厌恶的行业&#xff0c;如今似乎又焕发了新一春&#xff0c;足以颠覆我们的想象。 猪肉&…...

    2024/4/22 4:41:13
  15. python中的三大流程控制

    python中的三大流程控制一、顺序二、分支语句三、 循环四、流程控制例题&#xff1a;一、顺序 顺序结构就是代码一种自上而下执行的结构&#xff0c;这是Python默认的流程。 举例&#xff1a; 编写一个程序&#xff0c;提示用户按圆的半径计算圆的周长和面积。输入圆的半径: 5…...

    2024/4/30 9:45:11
  16. AutoML综述

    《taking human out of learning applications: a survey on automated machine learning》 AutoML出现的原因 机器学习大量人工干预&#xff1a; 特征提取、模型选择、参数调节 autoML试图将这些与特征、模型、优化、评价有关的重要步骤进行自动化的学习 autoML问题定义 机…...

    2024/4/27 2:29:25
  17. Liferay在处理文件的上传和下载

    例如:在添加Teacher的时候,一个表单,里面需要填写教师的信息,input 下拉,单选 等等,还要有多个文件需要上传,且这些文件还要分类别 例如:教师身份证支持多文件上传 教师表teacher 主键id 与教师表关联的 文件表teacherFile teacherId就是教师的主键 fileType文…...

    2024/4/25 11:05:01
  18. 为什么区块链巨头企业一定会诞生在中国的原因分析

    2000年以前传统方式买卖不再是终端为王&#xff0c;停留在买卖关系的时代已经万劫不复&#xff0c;得终端者得天下已演变为历史&#xff01; 2000年以后互联网的兴起&#xff0c;改变了终端和消费习惯&#xff1b;2019年互联网转型元年&#xff0c;年底的疫情延伸到2020年&…...

    2024/4/3 4:29:52
  19. Linux中Vim使用及账号用户管理

    Vim编辑器介绍 Vim是从 vi 发展出来的一个文本编辑器。代码补完、编译及错误跳转等方便编程的功能特别丰富&#xff0c;在程序员中被广泛使用。 简单的来说&#xff0c; vi 是老式的字处理器&#xff0c;不过功能已经很齐全了&#xff0c;但是还是有可以进步的地方。 vim 则…...

    2024/4/17 9:49:48
  20. Linux虚拟机的安装步骤

    Linux虚拟机的安装步骤 首先&#xff0c;安装VMware&#xff0c;比较简单&#xff0c;基本就是下一步。安装完成后打开VMware&#xff0c;点击加号创建虚拟机 首先&#xff0c; 弹出安装配置类型窗口&#xff0c;刚开始学习&#xff0c;选择自定义 下一步会出现版本兼容性选择…...

    2024/4/26 17:52:08

最新文章

  1. 用Scrapy 从数据挖掘到监控和自动化测试

    Scrapy 是一个 BSD 许可的快速高级网络爬虫和网络抓取框架&#xff0c;用于抓取网站并从其页面中提取结构化数据。它可以用于广泛的用途&#xff0c;从数据挖掘到监控和自动化测试。 安装scrapy pip install scrapy 爬虫示例 示例代码写入文件 import scrapyclass QuotesSp…...

    2024/5/2 7:26:24
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. Python读取文件里内容

    如果要读取一个文件里的内容是 # 文件名&#xff1a;db.txt 1 2 3 4代码如下 import requests f open("db.txt", mode"rb") content f.read() f.close()data content.decode(utf-8)# 存到 list 里 data_list data.split(\r\n) print(data_list)# 结果…...

    2024/5/1 9:42:44
  4. Django实现的登录注册功能

    1 前言 在Web开发中&#xff0c;用户登录和注册是最基本且必不可少的功能。Django&#xff0c;作为一个高级的Python Web框架&#xff0c;为我们提供了强大的工具和库来快速实现这些功能。下面&#xff0c;我将详细介绍如何使用Django来实现用户登录和注册功能。 2 功能介绍 …...

    2024/5/1 13:23:09
  5. 416. 分割等和子集问题(动态规划)

    题目 题解 class Solution:def canPartition(self, nums: List[int]) -> bool:# badcaseif not nums:return True# 不能被2整除if sum(nums) % 2 ! 0:return False# 状态定义&#xff1a;dp[i][j]表示当背包容量为j&#xff0c;用前i个物品是否正好可以将背包填满&#xff…...

    2024/5/1 10:25:26
  6. 【Java】ExcelWriter自适应宽度工具类(支持中文)

    工具类 import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet;/*** Excel工具类** author xiaoming* date 2023/11/17 10:40*/ public class ExcelUti…...

    2024/5/1 13:20:04
  7. Spring cloud负载均衡@LoadBalanced LoadBalancerClient

    LoadBalance vs Ribbon 由于Spring cloud2020之后移除了Ribbon&#xff0c;直接使用Spring Cloud LoadBalancer作为客户端负载均衡组件&#xff0c;我们讨论Spring负载均衡以Spring Cloud2020之后版本为主&#xff0c;学习Spring Cloud LoadBalance&#xff0c;暂不讨论Ribbon…...

    2024/5/1 21:18:12
  8. TSINGSEE青犀AI智能分析+视频监控工业园区周界安全防范方案

    一、背景需求分析 在工业产业园、化工园或生产制造园区中&#xff0c;周界防范意义重大&#xff0c;对园区的安全起到重要的作用。常规的安防方式是采用人员巡查&#xff0c;人力投入成本大而且效率低。周界一旦被破坏或入侵&#xff0c;会影响园区人员和资产安全&#xff0c;…...

    2024/5/1 4:07:45
  9. VB.net WebBrowser网页元素抓取分析方法

    在用WebBrowser编程实现网页操作自动化时&#xff0c;常要分析网页Html&#xff0c;例如网页在加载数据时&#xff0c;常会显示“系统处理中&#xff0c;请稍候..”&#xff0c;我们需要在数据加载完成后才能继续下一步操作&#xff0c;如何抓取这个信息的网页html元素变化&…...

    2024/4/30 23:32:22
  10. 【Objective-C】Objective-C汇总

    方法定义 参考&#xff1a;https://www.yiibai.com/objective_c/objective_c_functions.html Objective-C编程语言中方法定义的一般形式如下 - (return_type) method_name:( argumentType1 )argumentName1 joiningArgument2:( argumentType2 )argumentName2 ... joiningArgu…...

    2024/5/2 6:03:07
  11. 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】

    &#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】&#x1f30f;题目描述&#x1f30f;输入格…...

    2024/5/1 6:35:25
  12. 【ES6.0】- 扩展运算符(...)

    【ES6.0】- 扩展运算符... 文章目录 【ES6.0】- 扩展运算符...一、概述二、拷贝数组对象三、合并操作四、参数传递五、数组去重六、字符串转字符数组七、NodeList转数组八、解构变量九、打印日志十、总结 一、概述 **扩展运算符(...)**允许一个表达式在期望多个参数&#xff0…...

    2024/5/1 11:24:00
  13. 摩根看好的前智能硬件头部品牌双11交易数据极度异常!——是模式创新还是饮鸩止渴?

    文 | 螳螂观察 作者 | 李燃 双11狂欢已落下帷幕&#xff0c;各大品牌纷纷晒出优异的成绩单&#xff0c;摩根士丹利投资的智能硬件头部品牌凯迪仕也不例外。然而有爆料称&#xff0c;在自媒体平台发布霸榜各大榜单喜讯的凯迪仕智能锁&#xff0c;多个平台数据都表现出极度异常…...

    2024/5/2 5:31:39
  14. Go语言常用命令详解(二)

    文章目录 前言常用命令go bug示例参数说明 go doc示例参数说明 go env示例 go fix示例 go fmt示例 go generate示例 总结写在最后 前言 接着上一篇继续介绍Go语言的常用命令 常用命令 以下是一些常用的Go命令&#xff0c;这些命令可以帮助您在Go开发中进行编译、测试、运行和…...

    2024/5/1 20:22:59
  15. 用欧拉路径判断图同构推出reverse合法性:1116T4

    http://cplusoj.com/d/senior/p/SS231116D 假设我们要把 a a a 变成 b b b&#xff0c;我们在 a i a_i ai​ 和 a i 1 a_{i1} ai1​ 之间连边&#xff0c; b b b 同理&#xff0c;则 a a a 能变成 b b b 的充要条件是两图 A , B A,B A,B 同构。 必要性显然&#xff0…...

    2024/4/30 22:14:26
  16. 【NGINX--1】基础知识

    1、在 Debian/Ubuntu 上安装 NGINX 在 Debian 或 Ubuntu 机器上安装 NGINX 开源版。 更新已配置源的软件包信息&#xff0c;并安装一些有助于配置官方 NGINX 软件包仓库的软件包&#xff1a; apt-get update apt install -y curl gnupg2 ca-certificates lsb-release debian-…...

    2024/5/1 6:34:45
  17. Hive默认分割符、存储格式与数据压缩

    目录 1、Hive默认分割符2、Hive存储格式3、Hive数据压缩 1、Hive默认分割符 Hive创建表时指定的行受限&#xff08;ROW FORMAT&#xff09;配置标准HQL为&#xff1a; ... ROW FORMAT DELIMITED FIELDS TERMINATED BY \u0001 COLLECTION ITEMS TERMINATED BY , MAP KEYS TERMI…...

    2024/5/2 0:07:22
  18. 【论文阅读】MAG:一种用于航天器遥测数据中有效异常检测的新方法

    文章目录 摘要1 引言2 问题描述3 拟议框架4 所提出方法的细节A.数据预处理B.变量相关分析C.MAG模型D.异常分数 5 实验A.数据集和性能指标B.实验设置与平台C.结果和比较 6 结论 摘要 异常检测是保证航天器稳定性的关键。在航天器运行过程中&#xff0c;传感器和控制器产生大量周…...

    2024/4/30 20:39:53
  19. --max-old-space-size=8192报错

    vue项目运行时&#xff0c;如果经常运行慢&#xff0c;崩溃停止服务&#xff0c;报如下错误 FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory 因为在 Node 中&#xff0c;通过JavaScript使用内存时只能使用部分内存&#xff08;64位系统&…...

    2024/5/1 4:45:02
  20. 基于深度学习的恶意软件检测

    恶意软件是指恶意软件犯罪者用来感染个人计算机或整个组织的网络的软件。 它利用目标系统漏洞&#xff0c;例如可以被劫持的合法软件&#xff08;例如浏览器或 Web 应用程序插件&#xff09;中的错误。 恶意软件渗透可能会造成灾难性的后果&#xff0c;包括数据被盗、勒索或网…...

    2024/5/1 8:32:56
  21. JS原型对象prototype

    让我简单的为大家介绍一下原型对象prototype吧&#xff01; 使用原型实现方法共享 1.构造函数通过原型分配的函数是所有对象所 共享的。 2.JavaScript 规定&#xff0c;每一个构造函数都有一个 prototype 属性&#xff0c;指向另一个对象&#xff0c;所以我们也称为原型对象…...

    2024/5/1 14:33:22
  22. C++中只能有一个实例的单例类

    C中只能有一个实例的单例类 前面讨论的 President 类很不错&#xff0c;但存在一个缺陷&#xff1a;无法禁止通过实例化多个对象来创建多名总统&#xff1a; President One, Two, Three; 由于复制构造函数是私有的&#xff0c;其中每个对象都是不可复制的&#xff0c;但您的目…...

    2024/5/1 11:51:23
  23. python django 小程序图书借阅源码

    开发工具&#xff1a; PyCharm&#xff0c;mysql5.7&#xff0c;微信开发者工具 技术说明&#xff1a; python django html 小程序 功能介绍&#xff1a; 用户端&#xff1a; 登录注册&#xff08;含授权登录&#xff09; 首页显示搜索图书&#xff0c;轮播图&#xff0…...

    2024/5/1 5:23:20
  24. 电子学会C/C++编程等级考试2022年03月(一级)真题解析

    C/C++等级考试(1~8级)全部真题・点这里 第1题:双精度浮点数的输入输出 输入一个双精度浮点数,保留8位小数,输出这个浮点数。 时间限制:1000 内存限制:65536输入 只有一行,一个双精度浮点数。输出 一行,保留8位小数的浮点数。样例输入 3.1415926535798932样例输出 3.1…...

    2024/5/1 20:56:20
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57