Spring4 全细节回顾

news2024/11/17 9:37:52

spring细节回顾

1、IOC/DI

在这里插入图片描述

ApplicationContext接口是BeanFactory接口的子接口,Spring所有的东西都扔到了这里边。

1、Beans:Spring负责创建类对象并管理对象;

2、Core:核心类;

3、Context:上下文参数,获取外部资源,或者是管理注解等。

4、SPEL:expression包;

IOC功能:

IoC 完成的事情原先由程序员主动通过 new 实例化对象转交给 Spring 负责。

环境搭建:

四大核心jar包要有。

记住spring容器是ApplicationContext。

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"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
						http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- id 表示获取到对象标识 class 创建哪个类的对象-->
<bean id="peo" class="com.pshdhx.pojo.People"/>
</beans>
</xml>

Spring配置文件是基于Schema的。

schema文件的扩展名.xsd;

每次引入一个xsd文件都是一个namespace(====xmlns=“”)

如此,引入了xmlns,配置好了xsi的路径,在xml中就可以写引入的配置标签了。

Spring创建对象实例

//正常创建对象
People people = new People();
//利用spring容器创建对象
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
People peo = ac.getBean("peo",People.class);
//注意此处,并不是运行People peo = ac.getBean("peo",People.class);不是才创建的对象,而是一加载(配置文件)上下文的时候,bean对象就被创建了,通过People类的无参构造可以看出来。

Spring整合mybatis

1、必须有核心jar包,spring事务和common包+mybatis+jdbc等。

2、配置web.xml

​ 2.1:需要配置(参数):作用是找到Spring的配置文件。

​ 2.2:需要配置监听类::作用是帮助加载Spring配置文件。

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <!-- 上下文参数 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <!-- spring 配置文件 -->
        <param-value>classpath:applicationContext.xml</param-value>
	</context-param>
<!-- 封装了一个监听器,帮助加载 Spring 的配置文件 -->
    <listener>
    	<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>
</xml>

3、编写applicationContext.xml

​ 3.1:配置数据源的Bean

​ 3.2:配置Mybatis的SqlSessionFactory的Bean,内容属性是指向数据源Bean。

​ 3.3:配置Mybatis的Mapper包扫描器,属性是关联SqlSessionFactoryBean和包扫描basePackage。

​ 3.4:将Service注入到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/beans
	http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 数据源封装类 .数据源:获取数据库连接,spring-jdbc.jar 中-->
	<bean id="dataSouce" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
		<property name="url" value="jdbc:mysql://localhost:3306/ssm"></property>
		<property name="username" value="root"></property>
		<property name="password" value="root"></property>
	</bean>
	<!-- 创建 SqlSessionFactory 对象 -->
	<bean id="factory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<!-- 数据库连接信息来源于 dataSource -->
		<property name="dataSource" ref="dataSouce"></property>
	</bean>
	<!-- 扫描器相当于 mybatis.xml 中 mappers 下 package 标签,扫描 com.pshdhx.mapper 包后会给对应接口创建对象-->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<!-- 要扫描哪个包 -->
		<property name="basePackage" value="com.pshdhx.mapper"></property>
		<!-- 和 factory 产生关系 -->
		<property name="sqlSessionFactory" ref="factory"></property>
	</bean>

		<!-- 由 spring 管理 service 实现类 -->
	<bean id="airportService" class="com.pshdhx.service.impl.AirportServiceImpl">
		<property name="airportMapper" ref="airportMapper"></property>
	</bean>
</beans>
</xml>

Spring无法管理Servlet,因为其提供的接口要想被我们访问,需要被Tomcat的web容器管理。

4、让tomcat启动时自动加载Spring文件【web.xml,被tomcat管理了。】

5、控制器中初始化并且注入ServiceImpl

@WebServlet("/airport")
public class AirportServlet extends HttpServlet{
	private AirportService airportService;
	
    @Override
	public void init() throws ServletException {
		//对 service 实例化
		// ApplicationContext ac = newClassPathXmlApplicationContext("applicationContext.xml");
		//spring 和 web 整合后所有信息都存放在
		webApplicationContext ApplicationContext ac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
		airportService=ac.getBean("airportService",AirportServiceImpl.class);
	}
    @Override
    protected void service(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException {
    	req.setAttribute("list", airportService.show());
    	req.getRequestDispatcher("index.jsp").forward(req,resp);
    }
}

2、AOP

1、方法之间是纵向执行的,在某个方法的的前面或者是后面增加一个前置通知或者是后置通知,环绕通知,异常通知等。

2、不需要修改原有的方法,体现出程序的高扩展性。

概念:

​ 1、切点 pointCut

​ 2、前置通知 beforeAdvice

​ 3、后置通知 afterAdvice

​ 4、如果切点异常,会出现异常通知 throwsAdvice

2.1 AOP的demo

1、引入jar包

2、在spring配置文件中引入和配置AOP功能

3、实现通知事件,注意实现接口。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-usjg5bOI-1673189297416)(AOP包的引入.png)]

<?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 id="mybefore" class="com.pshdhx.advice.MyBeforeAdvice"></bean>
	<bean id="myafter" class="com.pshdhx.advice.MyAfterAdvice"></bean>
	<!-- 配置切面 -->
	<aop:config>
		<!-- 配置切点 -->
		<aop:pointcut expression="execution(* com.pshdhx.test.Demo.demo2())" id="mypoint"/>
		<!-- 通知 -->
		<aop:advisor advice-ref="mybefore" pointcut-ref="mypoint"/>
		<aop:advisor advice-ref="myafter" pointcut-ref="mypoint"/>
	</aop:config>
	<!-- 配置 Demo 类,测试使用 -->
	<bean id="demo" class="com.pshdhx.test.Demo"></bean>
</beans>

注意后置通知的参数:

arg0:切点方法的返回值;

arg1:切点方法对象;

arg2:切点方法的参数数组;

arg3:切点方法对象。

public class MyAfterAdvice implements AfterReturningAdvice {
    @Override
    public void afterReturning(Object arg0, Method arg1,Object[] arg2, Object arg3) throws Throwable {
    	System.out.println("执行后置通知");
    }
}

2.2 AOP的要点**

2.2.1 配置表达式

‘*’ 是通配符,匹配任意方法名,任意类名,任意一级包名

注意参数:* com.pshdhx.test.Demo.demo2((String,int) and args(name,age))

com.pshdhx.test.Demo.demo2(…)是匹配任意类型参数,但是不能直接使用。

<aop:pointcut expression="execution( *com.pshdhx.test.Demo.demo1(String,int)) and args(name1,age1)" id="mypoint"/>
<aop:pointcut expression="execution(*
com.pshdhx.test.Demo.demo1(String)) and args(name1)"
id="mypoint1"/>

注意execution的括号,不是全部的,而是方法的。参数的有另外的括号。

2.2.2 参数的配置

<aop:before method="mybefore"
pointcut-ref="mypoint" arg-names="name1,age1"/>

切点配置的参数可以不用和java方法的参数完全相同。

但是在通知配置上,参数的个数和名称必须和切点的配置相同,而且在java中的参数名称必须和通知配置上完全相同。

2.2.3 执行顺序

切点通知的执行顺序和切点配置的顺序有关。

2.3 实现AOP的两种方式

2.3.1 schema Base

前置通知和后置通知要实现固定的接口,在接口的方法中定义通知。

2.3.2 aspectJ方式

定义普通的类和普通的通知方法,但是要在配置文件中进行类和方法的配置。

以ThrowAdvice为例:当切点处有异常时,进行通知。并且通知在Service层不能够tryCatch,否则在最前边就捕获不到了。执行Demo.demo1时,无论是Throws或者是,TryCatch都能触发异常通知。

public class ThrowAdvice{
    public void printAdvice(Exception e){
        System.out.println("执行了异常通知"+e.getMessage());
    }
}
<bean id="throwAdvice" class="com.pshdhx.advice.ThrowAdvice"></bean>
<aop:config>
	<aop:aspect ref="throwAdvice">
		<aop:pointcut expression="execution(* com.pshdhx.test.Demo.demo(String,int)) and args(name1,age1)" id="mypoint"/>
		<aop:pointcut expression="execution(* com.pshdhx.test.Demo.demo1(String)) and args(name1)"	id="mypoint1"/>
		<aop:before method="mybefore" pointcut-ref="mypoint" arg-names="name1,age1"/>
		<aop:before method="mybefore1" pointcut-ref="mypoint1" arg-names="name1"/>
		<aop:after method="myafter"	pointcut-ref="mypoint"/>
		<aop:after-returning method="myaftering" pointcut-ref="mypoint"/>
		<aop:after-throwing method="throwAdvice" pointcut-ref="mypoint" throwing="e"/>
		<aop:around method="myarround" pointcut-ref="mypoint"/>
	</aop:aspect>
</aop:config>

2.3.3 环绕通知

前置通知+后置通知=环绕通知。

public class MyArround implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation arg0) throws Throwable {
        System.out.println("环绕-前置");
        Object result = arg0.proceed();//放行,调用切点方式,切点返回值
        System.out.println("环绕-后置");
        return result;
    }
}
<bean id="myarround"class="com.pshdhx.advice.MyArround"></bean>
<aop:config>
    <aop:pointcut expression="execution(* com.pshdhx.test.Demo.demo1())" id="mypoint"/>
    <aop:advisor advice-ref="myarround" pointcut-ref="mypoint" />
</aop:config>
<bean id="demo" class="com.pshdhx.test.Demo"></bean>

2.4 基于注解 Aspect方式***

Spring是不会自动寻找注解的,必须告诉Spring哪些下有注解。

新增引入:

<beans xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/context
       					  http://www.springframework.org/schema/context/spring-context.xsd
                           ">
</beans>

扫描的包如果是多个,用,隔开。

<context:component-scan base-package="com.pshdhx.t1,com.psd.t2"></context:component-scan>

2.4.1 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:context="http://www.springframework.org/schema/context"
       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
      http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd">

   <context:component-scan base-package="com.pshdhx.aop"></context:component-scan>

   <!--
      1、设置为true,是使用cglib动态代理
      2、设置为false,是使用jdk动态代理
      Are class-based (CGLIB) proxies to be created?
       By default, standard Java interface-based proxies are created.
      是否要创建基于类的(CGLIB)代理?默认情况下,标准创建了基于Java接口的代理。
   -->
   <aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>

</beans>

2.4.2 切点代码

package com.pshdhx.aop;

import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Component
public class PointCutClass {
    @Pointcut("execution(* com.pshdhx.aop.PointCutClass.testAop())")
    public void testAop(){
        System.out.println("测试AOP--这是切点");
    }
}

2.4.3 通知代码

package com.pshdhx.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class Advice {

    @Before("com.pshdhx.aop.PointCutClass.testAop()")
    public void myBefore(){
        System.out.println("前置通知!!!!");
    }
    @After("com.pshdhx.aop.PointCutClass.testAop()")
    public void myafter(){
        System.out.println("后置通知");
    }
    @AfterThrowing("com.pshdhx.aop.PointCutClass.testAop()")
    public void mythrow(){
        System.out.println("异常通知");
    }
    @Around("com.pshdhx.aop.PointCutClass.testAop()")
    public Object myarround(ProceedingJoinPoint p) throws
            Throwable{
        System.out.println("环绕-前置");
        Object result = p.proceed();
        System.out.println("环绕-后置");
        return result;
    }
}

2.4.4 测试代码

package com.pshdhx;

import com.pshdhx.aop.PointCutClass;
import com.pshdhx.utils.SpringUtils;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Author: pansd
 * Date: 2022/12/4 16:44
 * Description: 测试主类
 */
public class Test {
    public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        PointCutClass pointCutClass = ac.getBean("pointCutClass", PointCutClass.class);
        pointCutClass.testAop();
    }
}

3、代理设计模式

“设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。 使用设计模式是为了可重用代码、让代码更容易被他人理解、提高代码的可靠性。

AOP就是使用了代理设计模式;

3.1 什么是代理设计模式

为一个对象提供一个替身,以控制对这个对象的访问。即通过代理对象访问目标对象。这样做的好处为可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。

3.1.1 代理设计模式的优点

1、保护真实对象;(总裁)

2、让真实对象的职责更加明确和集中;(秘书做杂货)

3、便于扩展。(秘书处)

3.1.2 静态代理设计模式

由代理对象代理所有真实对象的功能,需要自己编写代理类,代理方法的每个功能点都需要重写。

缺点:当代理功能比较多时,代理类中方法需要写很多。

方法:真实对象和代理对象都需要实现同一个接口中的所有的方法。

3.2 JDK的动态代理

优点:jdk自带,不需要额外导入jar包;

缺点:真实对象必须实现接口,利用JDK的反射机制,效率不高;

3.2.1 JDK动态代理的代码

//定义接口
public interface FunctionInterface {
    void work();
}
//真实对象Manager实现接口
public class Manager implements FunctionInterface{

    @Override
    public void work() {
        System.out.println("work..............");
    }
}
//代理对象实现反射接口,增添功能[InvocationHandler]
public class ProxyObj implements InvocationHandler {
    private Manager manager = new Manager();
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("预约时间");
        Object result = method.invoke(manager, args);
        System.out.println("记录访客信息");
        return result;
    }
}
//测试方法
public class JDKProxyTest {
    public static void main(String[] args) {
        ProxyObj p = new ProxyObj();
        //第一个参数:反射时使用的类加载器
        //第二个参数:Proxy需要实现什么接口
        //第三个参数:通过接口对象调用方法时,需要调用哪个类的invoke方法
        FunctionInterface instance = (FunctionInterface) Proxy.newProxyInstance(JDKProxyTest.class.getClassLoader(),
                new Class[]{FunctionInterface.class}, p);
        instance.work();

    }
}

3.3 Cglib代理

实现原理:子类继承父类,重写父类的方法。super.work()前后添加功能;

cglib的优点:

1、它是基于字节码,不是基于反射,生成真实对象的代理对象,所以效率比jdk动态代理效率高;

缺点:

1、需要额外引入第三方的jar包。

​ asm包:解析字节码的包;cglib:功能jar包;

spring使用AOP功能时,真实对象和代理对象转换时,注意:

<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>

设置为true时,使用cglib动态代理;

设置为false,使用jdk动态代理。

3.3.1 cglib动态代理代码

public class Manager {
    public void work(){
        System.out.println("工作中....");
    }
}

//注意代理类实现cglib的接口
public class CglibProxy implements MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("调用方法前");
//        method.invoke(objects);
        methodProxy.invokeSuper(o,objects);
        System.out.println("调用方法后");
        return null;
    }
}
//cglib的测试类
package com.pshdhx;

import com.pshdhx.cglib.CglibProxy;
import com.pshdhx.cglib.Manager;
import net.sf.cglib.proxy.Enhancer;

/**
 * Author: pansd
 * Date: 2022/12/7 22:01
 * Description: TODO
 */
public class CglibTest {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(Manager.class);
        enhancer.setCallback(new CglibProxy());
        Manager manager = (com.pshdhx.cglib.Manager) enhancer.create();
        manager.work();

    }
}

4、SSM的配置文件整合

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee                       
	http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:applicationContext.xml</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
</web-app>

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 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/ssm"></property>
    	<property name="username" value="root"></property>
    	<property name="password" value="smallming"></property>
    </bean>
    <!-- SqlSessinFactory对象 -->
    <bean id="factory" class="org.mybatis.spring.SqlSessionFactoryBean">
    	<property name="dataSource" ref="dataSource"></property>
    	<property name="typeAliasesPackage" value="com.pshdhx.pojo"></property>
    </bean>
    <!-- 扫描器 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    	<property name="basePackage" value="com.pshdhx.mapper"></property>
    	<property name="sqlSessionFactory" ref="factory"></property>
    </bean>
    
    <!-- 注入 -->
    <bean id="usersService" class="com.pshdhx.service.impl.UsersServiceImpl">
    	<property name="usersMapper" ref="usersMapper"></property>
    </bean>
    
    <!-- aop -->
    <aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
    <bean id="mybefore" class="com.pshdhx.advice.MyBefore"></bean>
    <bean id="myafter" class="com.pshdhx.advice.MyAfter"></bean>
    <aop:config>
    	<aop:pointcut expression="execution(* com.pshdhx.service.impl.UsersServiceImpl.login(..))" id="mypoint"/>
    	<aop:advisor advice-ref="mybefore" pointcut-ref="mypoint"/>
    	<aop:advisor advice-ref="myafter" pointcut-ref="mypoint"/>
    </aop:config>
</beans>

4.1 原始servlet控制器

package com.pshdhx.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.pshdhx.pojo.Users;
import com.pshdhx.service.UsersService;
import com.pshdhx.service.impl.UsersServiceImpl;
//一启动就直接进入到login目录下,寻找index.jsp,我们需要到login.jsp
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
	private UsersService usersService;
	@Override
	public void init() throws ServletException {
		WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
		usersService = wac.getBean("usersService",UsersServiceImpl.class);
	}
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		req.setCharacterEncoding("utf-8");
		Users users = new Users();
		users.setUsername(req.getParameter("username"));
		users.setPassword(req.getParameter("password"));
		Users user = usersService.login(users);
		if(user!=null){
			resp.sendRedirect("main.jsp");
		}else{
			resp.sendRedirect("login.jsp");
		}
	}
}

4.2 AOP和Filter的区别

AOP拦截的是切点的方法;

Filter拦截的是某个请求;

4.3 属性的自动注入

<!-- 原始方式 -->
<bean id="teacher" class="com.pshdhx.test.Teacher"></bean>
<bean id="people" class="com.pshdhx.test.People">
	<property name="teacher" ref="teacher"></property>
</bean>

<bean id="people" class="com.pshdhx.test.People" autowire="default"></bean>
<!-- 实际上有五个值,default(默认走上边的全局,全局也默认是default), 
no (不自动注入),
byName(找其他bean的id)也向容器中去寻找@Component("pshdhx"),
byType(找全局类型,往class中对应,但是绝对不能出现两个及其以上的注入),
contructor(必须要在people类中提供一个构造方法,有Teacher参数的和无参构造,但是找类的时候,也是通过byName找的,如果上边的id变为了teacher1,则找寻不到。teacher=null) -->    

全局注入:直接在xsi:schemaLocation=“写就行”

default-autowire=“byName”

总结:基本上就是省略了ref指向的那一行属性的配置。

4.4 spring加载外部属性文件

首先xsi引入context

自动注入的优先级特别高,会先进行实例的注入。但是实例的值,是用的外部文件引入的,此时外部文件的值还没有被加载进spring,所以会报错。

自动注入影响的是只有ref的指向对象,而不影响字符串(sqlSessionFactoryBeanName)。

 <!-- SqlSessinFactory对象 -->
    <bean id="factory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<!--     	<property name="dataSource" ref="dataSource"></property> -->
    	<property name="typeAliasesPackage" value="com.pshdhx.pojo"></property>
    </bean>

 <!-- 扫描器 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    	<property name="basePackage" value="com.pshdhx.mapper"></property>
		<!--     	<property name="sqlSessionFactory" ref="factory"></property> -->
        <property name="sqlSessionFactoryBeanName" value="factory"></property>
    </bean>

db.properties

jdbc.driverName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm
jdbc.username=root
jdbc.password=pshdhx
<?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/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
		http://www.springframework.org/schema/context
       	http://www.springframework.org/schema/context/spring-context.xsd">	
<context:property-placeholder location="classpath:db.properties,classpath:second.properties" />

	<!-- 数据源 -->
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="${driverName}"></property>
		<property name="url" value="${jdbc.url}"></property>
		<property name="username" value="${jdbc.username}"></property>
		<property name="password" value="${jdbc.password}"></property>
	</bean>

4.5 scope属性

//<bean id="teacher" class="com.pshdhx.vo.Teacher" scope="singleton"></bean> <!-- 默认单例 -->
Teacher t1 = ac.getBean("teacher", Teacher.class);
Teacher t2 = ac.getBean("teacher", Teacher.class);//teacher区分大小写
System.out.println(t1==t2);//true

单例模式:一个bean对应的对象,默认是单例的,在整个对象中只初始化一次。无论获取多少次对象,只初始化一次。

<bean id="teacher" class="com.pshdhx.vo.Teacher" scope="singleton"></bean> <!-- 默认单例 -->
<bean id="teacher" class="com.pshdhx.vo.Teacher" scope="prototype"></bean> <!-- 改为多例 -->

request:每次请求,重新实例化;所以是web对象;

作用:在一个应用程序中,保证最多有一个实例。

优点:

1、提升运行效率;

2、实现数据共享;案例:application对象(单例)是四大作用于对象,有效范围是tomcat启动到关闭一直有效。

4.6 手写单例

public class SingleTon{
    //由于对象需要静态方法调用,把获取对象的方法设置为static,方法设置为了static,则变量也设置为static
    //由于对象是static,必须设置访问权限修饰符为private,如果是public,则可以通过类直接调用对象了,不走获取对象的接口
    private static SingleTon singleTon;
    private SingleTon(){}
    private static SingleTon getInstance(){
        if(singleTon == null){
            syncronized(SingleTon.class){
                //防止多线程情况下,需要再判断一次[双重认证]
                if(singleTon == null){
                    singleTon =  new SingleTon();
                }
            }
        }
        return singleTon;
    }
}

懒汉式,由于添加了锁,效率会低。

饿汉式,解决了懒汉式中多线程访问可能出现同一个对象和效率低下的问题。

public class SingleTon{
	private static SingleTon singleTon = new SingleTon();
    private SingleTon(){}
    public static SingleTon getInstance(){
        return singleTon;
    }
}

5、声明式事务基本配置步骤

1、编程式事务:提交和回滚自己编写;

2、声明式事务:事务控制代码由Spring写好,程序员只需要声明出那些方法需要进行事务控制和如何进行事务控制。

代码:

3、事务传播行为

name="*"支持通配符

readonly=“boolean" 是否是只读事务

如果为true,则告诉数据库此事务为只读事务。数据查询会优化,对性能有一定提升。所以只是需要查询的方法,建议使用此数据。

如果为false,默认值,增加,删除,修改,建议使用此方法;

propagation=“” 控制事务传播行为,当一个具有事务控制的方法被另一个有控制方法调用后,需要如何管理事务。(新建事务?还是再事务中执行,还是挂起报异常)

required:必须得有事务。默认值。

supports:如果当前有事务,就按照事务来;如果当前没有事务,就按照非事务状态来;

mandatory:必须再事务中执行,如果当前有事务,就在事务中执行,如果没有事务,就报错。

required_new:必须再事务中执行,如果当前有事务,挂起;如果当前没有事务,新开一个事务,两个事务没有任何关系。

not_supported:必须在非事务中执行,如果当前有事务,挂起当前事务。

never:必须在非事务状态下执行,怎么都不能有事务。如果当前有事务,报错。

nested:必须在事务状态下执行,如果没有事务,就新建事务。如果有事务,就创建一个嵌套事务。两个事务有关系,子事务被大事务所包含。

6、 事务隔离级别

在多线程或者是并发访问情况下,如何保证所访问到的数据是对的。

6.1 脏读

事务A读取到事务B中未提交的数据,但是事务B的数据可能发生改变,此时认为事务A读取过程为脏读。

6.2 幻读

事务A按照特定条件查询出结果,事务B去新增了一条符合条件的数据,事务A中查出的数据和数据库中的数据不一致,事务A好像出现了幻觉,此时加表锁

特点:

​ 针对于的操作是新增和删除数据;

​ 两次事务的结果。

6.3 不可重复读

当事务A在第一次读取数据后,事务B对事务A读取的数据进行了修改,事务A中再次读取的数据和之前读取的数据不一致,该过程为不可重复度。

特点:

​ 主要是针对于某行数据,或者是行中的某一列。

​ 主要是针对的是修改操作。

​ 两次读取在同一个事务内。

场景:张三去取钱,发现余额为20000,想要取出15000。与此同时,他老婆取出了15000,张三再取钱时,发现钱不够了。所以要在读取到20000余额时,对该数据加上行锁

6.4 序列化(可串行读)

排队操作,对整个表进行加锁。一个事务在操作完成数据之后,另一个事务才能操作这个表。【是最安全的,但是效率最低。】

isolation="READ_COMMITTED" READ_UNCOMMITTE  REPEATABLE_READ  SERIALIZABLE  DEFAULT

6.5 解决和缺陷

读未提交:可以读取未提交的数据,可能出现脏读,幻读,不可重复读。

​ 效率最高;

读已提交:只能读取其他事务中已提交的数据。可以防止脏读。可能出现不可重复度和幻读,【已提交和加锁没有关系】。

REPEATABLE_READ:(Repeatable Read 可重复的读取),可以对读取的数据进行加锁,避免其他人对其进行修改。可以防止不可重复度和脏读(因为加了锁,别人无法对其进行修改),但是不能防止幻读。

SERIALIZABLE

排队操作,对整个表进行加锁。一个事务在操作完成数据之后,另一个事务才能操作这个表。【是最安全的,但是效率最低。】

6.6 代码配置

	<!-- spring-jdbc中 -->
	<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

	</bean>
	<!-- 配置声明式事务,要想其生效,就必须有切点(基于通知)。真正控制那些方法实现事务,则必须控制具体的方法 -->
	<tx:advice id="txAdvice" transaction-manager="txManager">
		<tx:attributes>
			<tx:method name="userInsert" propagation="REQUIRED" isolation="SERIALIZABLE" rollback-for="java.lang.Exception"/>
			<tx:method name="ins*"/>
			<tx:method name="del*"/>
			<tx:method name="upd*"/>
		</tx:attributes>
	</tx:advice>

	<aop:config>
		<aop:pointcut id="mypoint" expression="execution(* com.pshdhx.service.impl.*.*(..))"/>
		<!-- 声明式事务相当于通知,多饶了一个圈 -->
		<aop:advisor advice-ref="txAdvice" pointcut-ref="mypoint" />
	</aop:config>

6.7 异常回滚

rollback-for=“java.lang.Exception” 异常类型全限定路径

当出现什么异常时,需要进行回滚

建议:给定该属性值。

​ 手动抛异常 throw new Exception时,一定要给该属性值。

no-rollback-for=“”

​ 当出现什么异常时,不回滚。

7、常用注解

spring中常用的注解:

1、@Component 创建类对象,相当于

2、@Service与@Component功能相同。

3、@Repository与@Component功能相同,写在数据访问层上。

4、@Controller与@Component功能相同,写在控制器上。

5、@Autowired(spring)不需要写setget方法。默认按照ByType注入。

6、@Resource(javax) 默认按照ByName注入,没有按照ByType注入,不需要写setget方法。

7、@Value获取属性文件内容

8、@PointCut 定义切点

9、@Aspect 定义切面类 @Before @After @AfterReturning(切点必须正常执行)@Around

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/148742.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机器学习(4)——周志华

归纳偏好 若非必要&#xff0c;勿增实体 若多个算法都能解决同一个问题&#xff0c;则选取最简单的算法 当前什么样的偏好与问题更匹配&#xff0c;必须对问题有一个清楚的认识

shader基础入门(2)(VertexHelper)

VertexHelper&#xff08;顶点帮助器/顶点辅助类/顶点助手&#xff09; 官方资料版本&#xff1a;2019.1 使用需要继承&#xff1a;using UnityEngine.UI; 描述 可以帮助为 UI 生成网格的实用程序类。 此类实现 IDisposable 以帮助进行内存管理。 属性 currentIndexCount …

【vim工具的使用】

目录&#xff1a;前言一、普通/命令模式1.文件中移动 - 12.文件中移动 - 23.复制、粘贴、剪切、删除4.行内删除5.撤回6.替换7.高亮选中8.逐单词移动 - 3二、底行模式1.退出vim2.设置行号3.替换4.搜索3.不退出vim的情况下进行操作4.多文件操作三、替换模式四、插入模式总结前言 …

Python递归小练习

递归算法是常见的基础算法之一&#xff0c;阶乘、青蛙跳台、兔子算法等便是递归算法中典型的例子。 1、阶乘以6的阶乘为例&#xff0c;计算的过程如下图所示 Python代码实现如下&#xff1a; def jiecheng(n):if n 1:result 1else:result n * jiecheng(n - 1)return resul…

蓝桥杯寒假集训第九天(回文日期)

没有白走的路&#xff0c;每一步都算数&#x1f388;&#x1f388;&#x1f388; 题目描述&#xff1a; 输入一行数据&#xff0c;这个数据是从10000101到89991231&#xff0c;输出这个数据后面的第一个回文数&#xff0c;以及输出第一个ABABBABA型的回文数。 注意&#xff1…

跟着博主一起刷题:《剑指offer》(第五天)

跟着博主一起刷题 这里使用的是题库&#xff1a; https://leetcode.cn/problem-list/xb9nqhhg/?page1 目录剑指 Offer 37. 序列化二叉树剑指 Offer 38. 字符串的排列剑指 Offer 40. 最小的k个数剑指 Offer 37. 序列化二叉树 剑指 Offer 37. 序列化二叉树 序列化&#xff1a; …

windows下mmclassification安装教程

文章目录mmclassification版本0.23.1一.官方安转教程二.安装教程mmclassification版本0.23.1 一.官方安转教程 官网 二.安装教程 创建conda环境 conda create --name openmmlab python3.8 -y进入创建的环境 conda activate openmmlab安转pytorcch conda install pytorch torc…

CSS知识点精学5-定位装饰

目录 一.定位 1&#xff0e;定位的基本介绍 2.定位的基本使用 3.静态定位 4.相对定位 5.绝对定位 6.子绝父相 a.优化学成网站推荐课程卡片 b.绝对定位盒子的居中&#xff08;案例&#xff09; 8.固定定位 9.元素的层级关系 二.装饰 1.垂直对齐方式 2.光标类型 3…

计算机网络实验报告

计算机网络实验报告 文章目录计算机网络实验报告一、验证性实验ipconfig实作一实作二问题ping实作一实作二问题tracert实作一问题一问题二问题三ARP实作一实作二实作三问题DHCP实作一问题netstat实作一实作二DNS实作一实作二实作三问题cache实作二二、Wireshark 实验数据链路层…

果蔬消毒机行业市场深度监测及发展趋势预测分析

2023-2029年中国果蔬消毒机行业市场深度监测及发展趋势预测报告报告编号&#xff1a;1691217本报告著作权归博研咨询所有&#xff0c;未经书面许可&#xff0c;任何组织和个人不得以任何形式复制、传播或输出中华人民共和国境外。任何未经授权使用本报告的相关商业行为都将违反…

STP生成树基础,一个难点

技术背景&#xff1a;二层交换机网络的冗余性与环路 二层环路带来的问题&#xff08;三层环路&#xff0c;ttl跳数达到一定次数会丢弃&#xff09; 典型问题 1&#xff1a;广播风暴不停的在接口内复制转发广播 2&#xff1a;MAC地址漂移 sw1接口1与2&#xff0c;对sw3的接收ma…

CentOS7.x下部署oracle19c环境

CentOS7.x下部署oracle19c环境 文章目录CentOS7.x下部署oracle19c环境前言一、环境准备工作1.1、虚拟机搭建及关闭防火墙和selinux1.2、RPM包预安装1.3、检查安装情况用户组已创建完成1.4、创建目录1.5、修改/etc/hosts 文件1.6、设置oracle口令1.7、设置环境变量1.8、将oracle…

[LeetCode周赛复盘] 第 327 场周赛20230108

[LeetCode周赛复盘] 第 327 场周赛20230108 一、本周周赛总结二、 [Easy] 6283. 正整数和负整数的最大计数1. 题目描述2. 思路分析3. 代码实现三、[Medium] 6285. 执行 K 次操作后的最大分数1. 题目描述2. 思路分析3. 代码实现四、[Medium] 6284. 使字符串总不同字符的数目相等…

10、ThingsBoard-租户

1、租户的概念 目前,有很多的系统都是以多租户的形式来设计的,目的是为了实现数据隔离,thingsboard中也是如此。但是thingsboard把租户在抽象成了一种实体,后续还会讲解其它的实体;用官方的语言解释租户:您可以将租户视为一个单独的业务实体:它是拥有或生产设备和资产的…

Java中ThreadLocal说明

1、ThreadLocal是什么 ThreadLocal&#xff0c;即线程变量&#xff0c;是一个以ThreadLocal对象为键、任意对象为值的存储结构。 这个结构被附带在线程上&#xff0c;也就是说一个线程可以根据一个ThreadLocal对象查询到绑定在这个线程上的一个值。 ——《Java并发编程艺术》如…

GrapeCity Documents Data Viewer[GcDataViewer] Crack

GrapeCity Documents Data Viewer&#xff0c;简称GcDataViewer&#xff0c;是一个统一的基于 JavaScript 的客户端查看器&#xff0c;旨在加载和预览与数据相关的所有流行文档格式。目前&#xff0c;查看器支持 XLSX、SSJSON 和 CSV 格式。除了仅加载数据文件外&#xff0c;数…

卷径计算(厚度累计法/膜厚积分法)

卷径计算的截面积法请参看下面的文章链接: 卷径计算详解(通过卷绕的膜长和膜厚进行计算)_RXXW_Dor的博客-CSDN博客有关卷绕+张力控制可以参看专栏的系列文章,文章链接如下:变频器简单张力控制(线缆收放卷应用)_RXXW_Dor的博客-CSDN博客_收放卷应用张力控制的开闭环算法,…

“/ArcGIS/services”应用程序中的服务器错误

本文迁移自本人网易博客&#xff0c;写于2013年1月5日No Content说明: 执行当前 Web 请求期间&#xff0c;出现未处理的异常。请检查堆栈跟踪信息&#xff0c;以了解有关该错误以及代码中导致错误的出处的详细信息。 异常详细信息: System.Web.HttpException: No Content源错误…

第三章 图形初阶

我曾经多次向客户展示以数字和文字表示的、精心整理的统计分析结果&#xff0c;得到的只是客户呆滞的眼神&#xff0c;尴尬得房间里只能听到鸟语虫鸣。然而&#xff0c;当我使用图形向相同的用户展示相同的信息时&#xff0c;他们往往会兴致盎然&#xff0c;甚至豁然开朗。我经…

jQuery控制元素的显示与隐藏(三种方式对比)

hide和show hide:是$(“.类名”)或$(“#标签名”)或$(“标签名”).hide() show:是$(“.类名”)或$(“#标签名”)或$(“标签名”).show() 元素直接消失&#xff0c;没有任何动态效果 slideToggle 通过控制元素的高度来显示与隐藏&#xff0c;因此会有动画效果。slideToggle如果…