板子类的东西:
<?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:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
自动装配
按之前学到的我们配置三个类,人,猫,狗,人有猫和狗两个类
public class Dog {
public void show(){
System.out.println("wang~~~");
}
}
public class Cat {
public void show(){
System.out.println("miao~~~");
}
}
public class User {
private Cat cat;
private Dog dog;
private String name;
//get set方法
}
beans.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:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dog" class="com.study.pojo.Dog"/>
<bean id="cat" class="com.study.pojo.Cat"/>
<bean id="user" class="com.study.pojo.User">
<property name="dog" ref="dog"/>
<property name="cat" ref="cat"/>
<property name="name" value="林"/>
</bean>
</beans>
然后,测试是行得通的。
public class Mytest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
User user = context.getBean("user", User.class);
user.getCat().show();
user.getDog().show();
}
}
byname
按名称自动装配,
使用byname的自动装配,
<bean id="dog" class="com.study.pojo.Dog"/>
<!--<bean id="dog11" class="com.study.pojo.Dog"/>这个就不能检索出来-->
<bean id="cat" class="com.study.pojo.Cat"/>
<bean id="user" class="com.study.pojo.User" autowire="byName">
<property name="name" value="林"/>
</bean>
bytype
按类型自动装配,首先要保证同一类型的对象,在spring容器中唯一,如果不唯一,会报不唯一的异常。
<bean id="user" class="com.study.pojo.User" autowire="byType">
<property name="name" value="林"/>
</bean>
使用注解
jdk1.5开始支持注解,spring2.5开似乎全面支持注解
准备工作:利用注解的方式注入属性。
在spring配置文件中引入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:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c" 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/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:annotation-config/> </beans>
开启属性注释支持!
<context:annotation-congfig/>
@Autowired
- Autowired是按类型自动装配的,不支持id匹配
- 需要导入context的包
<context:annotation-config/>
<bean id="dog" class="com.study.pojo.Dog"/>
<bean id="cat" class="com.study.pojo.Cat"/>
<bean id="user" class="com.study.pojo.User"/>
@Autowired
private Cat cat;
@Autowired
private Dog dog;
private String name;
//set方法就不需要了
拓展
@Autowired(required=false) 说明:false,对象可以为null;true对象必须存东西,不能为null。默认为true
@Qualifier不能单独使用,必须搭配上@Autowired来使用, @Autowired是根据类型自动装配的,加上@Qualifier则可以根据byName的方式自动装配
@Autowired
@Qualifier(value = "cat1")
private Cat cat;
@Autowired
private Dog dog;
private String name;
当cat有多个的时候不指定会报错。所以通过@Qualifier进行指定。
<bean id="dog" class="com.study.pojo.Dog"/>
<bean id="cat1" class="com.study.pojo.Cat"/>
<bean id="cat2" class="com.study.pojo.Cat"/>
<bean id="cat" class="com.study.pojo.Cat"/>
<bean id="user" class="com.study.pojo.User"/>
@Resource
- @Resource如有指定的name属性,酰胺该属性进行byname方式查找装配。
- 其次在进行默认的byname方式进行装配
- 如果以上都不成功,则按bytype的方式进行自动装配。
- 都不成功则异常。
@Autowired与@Resource异同:
@Autowired与@Resource都可以用来装配bean。都可以写在字段上,或写在setter方法上。
@Autowired默认按类型装配(属于spring规范),默认情况下必须要求依赖对象必须存在,如果要允许null 值,可以设置它的required属性为false,如:@Autowired(required=false) ,如果我们想使用名称装配可以结合@Qualifier注解进行使用
@Resource(属于J2EE复返),默认按照名称进行装配,名称可以通过name属性进行指定。如果没有指定name属性,当注解写在字段上时,默认取字段名进行按照名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。
@Autowired是属于spring托管,在idea上显示出来(叶子标识),@Resource属于java托管,不会显示出来。
它们的作用相同都是用注解方式注入对象,但执行顺序不同。@Autowired先byType,@Resource先byName。使用注解进行开发
使用注解开发必须导入aop包
就是我们现在不使用beans.xml
进行配置了,我们对类直接进行操作。bean的实现
我们之前使用bean的标签进行bean注入,现在我们使用注解进行bean的注入
配置扫描那些包下的注解
<context:component-scan base-package="com.study.pojo"/>
在指定包下编写类,添加注解
@Component("user") //相当于配置文件中<bean id="user" class="当前注解的类 public class User { public String name="林苏泽"; }
测试
public class Mytest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); User user = context.getBean("user", User.class); System.out.println(user.name); } }
属性注入
使用注解注入属性
有set方法放set方法上,没set方法放属性上
@Value("林苏泽")
//相当于配置文件中的<property name="name" value="林苏泽"/>
public String name;
@Value("林苏泽")
public void setName(String name) {
this.name = name;
}
衍生注解
这些注解可以代替配置文件中的配置步骤。
@Component三个衍生注解
为了更好的进行分层,Spring可以使用其它三个注解,功能一样,目前使用哪一个功能都一样。
- @Controller:controller层
- @Service:service层
- @Repository:dao层
作用域
@scope
singleton:默认的,Spring会采用单例模式创建这个对象。关闭工厂 ,所有的对象都会销毁。
prototype:多例模式。关闭工厂 ,所有的对象不会销毁。内部的垃圾回收机制会回收
@Controller("user") @Scope("prototype") public class User { @Value("林苏泽") public String name; }
小结
xml与注解比较
xml可以适用任何场景,结构清晰维护简单。
注解不是自己提供的类是用不了,开发比较简单
推荐最佳实践xml与注解整合开发:
- xml管理bean
- 注解完成属性注入
- 使用过程中,可以不用扫描,扫描是为了类上的注解
<context:annotation-config/>
作用:
- 进行注解驱动注册,从而使注解生效
- 用于激活那些已经在spring容器里注册过的bean上面的注解,也就是显示的向spring注册
- 如果不扫描包,就需要手动配置bean
- 如果不加注解驱动,则注入的值为null
基于java类进行配置
JavaConfig 原来是 Spring 的一个子项目,它通过 Java 类的方式提供 Bean 的定义信息,在 Spring4 的版本, JavaConfig 已正式成为 Spring4 的核心功能
编写一个Dog类
//这个类标注为Spring的一个部件,放到容器里。 @Component public class Dog { public String name; public String getName() { return name; } @Value("dog") public void setName(String name) { this.name = name; } }
新建一个config配置包,编写一个Myconfig配置类
@Configuration //代表一个配置类 public class MyConfig { @Bean //通过方法注册一个bean,这里的返回值就是bean的类型,方法名就是bean的id public Dog dog(){ return new Dog(); } }
测试:这里注意与配置
beans.xml
不同的是使用的方法不同,beans.xml
用的方法是ClassPathXmlApplicationContext
,而配置类用的是AnnotationConfigApplicationContext
public class Mytest { public static void main(String[] args) { //通过AnnotationConfigApplicationContext这个方法,与bean配置xml不同。 ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class); Dog dog = context.getBean("dog", Dog.class); System.out.println(dog.name); } }
如何导入其他配置
在写一个配置类和实体类@Component public class Cat { private String name; public String getName() { return name; } @Value("小猫") public void setName(String name) { this.name = name; } } @Configuration public class MyConfig2 { @Bean public Cat cat(){ return new Cat(); } }
注意这里
Cat
的name
是private
所以我们只能是通过getName
方法拿到。
然后把这个新创建的配置类导入到之前的配置类中。就是加了@Import(MyConfig2.class)
一句.
@Configuration //代表一个配置类
@Import(MyConfig2.class)//导入合并其他配置类,类似配置文件中的include标签
public class MyConfig {
@Bean //通过方法注册一个bean,这里的返回值就是bean的类型,方法名就是bean的id
public Dog dog(){
return new Dog();
}
}
测试,通过测试我们可以看到,Dog
和Cat
中的都能拿到。
public class Mytest {
public static void main(String[] args) {
//通过AnnotationConfigApplicationContext这个方法,与bean配置xml不同。
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
Dog dog = context.getBean("dog", Dog.class);
Cat cat = context.getBean("cat", Cat.class);
System.out.println(cat.getName());
System.out.println(dog.name);
}
}
代理模式
为什么要学习代理模式?
因为这就是SpringAOP的底层 [springAOP和SpringMVC]面试重点
代理模式:
静态代理
动态代理
静态代理
静态代理角色分析:
抽象角色:一般使用接口或者抽象类来实现
真实角色:被代理的角色
代理角色:代理真是角色,代理真实角色后,一般会做一些附属的操作
客户端:使用代理角色来进行一些操作
Rent.java
抽象角色,一般是指抽象活动
//抽象角色:租房
public interface Rent {
public void rent();
}
Host.java
真实角色:房东要租房
//真实角色:房东,
//房东需要出租房子
public class Host implements Rent{
@Override
public void rent() {
System.out.println("房屋出租");
}
}
Proxy
代理角色,中介
//代理角色,中介
//房东委托中介进行出租,所以中介也有出租
public class Proxy implements Rent {
private Host host;//知道房东是谁,知道代理的真实对象是谁
public Proxy() {
}//无参构造
public Proxy(Host host) {
//有参构造
this.host = host;
}
//租房这个抽象活动
@Override
public void rent() {
//中间可以有中介自己的一些操作。
//比如看房
seeHouse();
host.rent();//因为是替房东出租的所以是房东类调用方法
//再比如,缴纳中介费
fare();
}
public void seeHouse(){
System.out.println("中介带房客看房");
}
public void fare(){
System.out.println("房客向中介缴纳中介费");
}
}
Client.java
客户:去租房
//顾客类,一般客户都会去找代理
public class Client {
public static void main(String[] args) {
//房东要租房
Host host = new Host();
//中介代理房东去操作,
Proxy proxy = new Proxy(host);
//客户去找中介去租房,
proxy.rent();
}
}
分析:在这个过程中,顾客直接接触的是中介,就如用真实情况一样,租客接触不到房东,
但仍旧能通过中介租到房东的房子。这就是所谓的代理模式。
静态代理模式的好处
- 可以使得我们的真实角色更加纯粹,不再去关注一些公共的事情。(如房东只管租房即可,看房等操作不需要房东关心)
- 公共的业务由代理来完成,实现了业务的分工,
- 公共业务发生扩展时变得更加集中和方便
缺点:
- 类多了,工作量变大了,开发效率降低了。
我们想要静态代理的好处,而不想要静态代理的缺点,所以就有了动态代理
动态代理
- 动态代理和静态代理角色一致
- 动态代理的代理类时动态生成的,静态代理的代理类是我们提前写好的
- 动态代理分为两类,一类是基于接口动态代理,另一类是基于类的动态代理
- 基于接口的动态代理--JDK动态代理
- 基于类的动态代理--cglib
- 现在用的比较多的是javasist来生成动态代理
- 我们这里使用JDK的原生代码来实现
JDK的动态代理需要了解两个类
核心的两个类:InvocationHandler和Proxy
InvocationHandler:调用处理程序
Object invoke(Object proxy, 方法 method, Object[] args);
//参数
//proxy - 调用该方法的代理实例
//method -所述方法对应于调用代理实例上的接口方法的实例。方法对象的声明类将是该方法声明的接口,它可以是代理类继承该方法的代理接口的超级接口。
//args -包含的方法调用传递代理实例的参数值的对象的阵列,或null如果接口方法没有参数。原始类型的参数包含在适当的原始包装器类的实例中,例如java.lang.Integer或java.lang.Boolean 。
Proxy:代理
//生成代理类
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
rent.getClass().getInterfaces(),this);
}
代码实现:
抽象角色和真实角色和之前一样。ProxyInvocationHandler.java
代理角色
public class ProxyInvocationHandler implements InvocationHandler {
private Object target;
public void setTarget(Object target) {
this.target = target;
}
//生成代理类,重点是第二个参数,获取代理的抽象角色,之气那都是一个角色,现在可以dialing一类
public Object getProxy() {
return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
//proxy :代理类method代理类的调用处理程序的方法对象,
//处理代理实力上的方法调用并返回结果。
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//可以加其他业务
see();
//核心:本质利用反射实现
Object invoke = method.invoke(target, args);
fare();
return invoke;
}
//看房:
public void see(){
System.out.println("看房");
}
//缴费
public void fare(){
System.out.println("缴费");
}
}
Client.java
public class Client {
public static void main(String[] args) {
//真实角色
Host host = new Host();
//代理实例中的调用处理程序
ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();
proxyInvocationHandler.setTarget(host);//把真实角色放置进去
Rent proxy = (Rent) proxyInvocationHandler.getProxy();// 动态生成对应的代理类
proxy.rent();
}
}
核心:一个动态代理,一般代理某一业务,一个动态代理可以代理多个类,代理的是接口。
动态代理的好处:
- 可以使得我们的真实角色更加纯粹,不再去关注一些公共的事情。(如房东只管租房即可,看房等操作不需要房东关心)
- 公共的业务由代理来完成,实现了业务的分工,
- 公共业务发生扩展时变得更加集中和方便
- 一个动态代理类代理的是一个接口,一般就是某一类业务
- 一个动态代理可以代理多个类,代理的是接口.
AOP
AOP是面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术,
AOP降低耦合性,提高程序的可重用性,勇士提高了开发效率
- 横切关注点:跨越应用程序多个模块的方法或功能。是与我们业务逻辑无关的,但我们需要关注的部分,就是横切关注点
如日志,安全,缓存,事务等等 - 切面(ASPECT): 横切关注点 被模块化的特殊对象。是一个类
- 通知(Advice): 切面必须要完成的工作。是类中的方法。
- 目标(Target): 被通知的对象
- 代理(Proxy): 向目标对象应用通知之后创建的对象。
- 切入点(PointCut): 切面通知执行的"地点"的定义。
- 连接点(JointPoint): 与切入点匹配的执行点。
主要有五种类型的通知,
- 前置通知,方法前
- 后置通知,方法后
- 环绕通知,方法前后
- 异常抛出通知,方法抛出异常时 {不常用}
- 引介通知,类中天界新的方法属性 {不常用}
有三种使用Spring实现AOP
首先导入依赖包
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.22.1</version>
</dependency>
第一种实现方式:通过SpringAPI实现
业务接口和实现类
public interface UserService {
public void add();
public void delete();
public void query();
public void update();
}
public class UserServiceImpl implements UserService {
@Override
public void add() {
System.out.println("添加");
}
@Override
public void delete() {
System.out.println("删除");
}
@Override
public void query() {
System.out.println("查询");
}
@Override
public void update() {
System.out.println("修改");
}
}
然后写两个增强类,就是加入的东西,一个前置一个后置,
两者调用的接口不用,通过接口就能看出那个是前置那个是后置。
public class LogBefore implements MethodBeforeAdvice {
//method : 要执行的目标方法
//args : 被调用的方法的参数
//target: 目标对象
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println(target.getClass().getName()+"的"+method.getName()+"方法执行了");
}
}
public class LogAfter implements AfterReturningAdvice {
//returnValue : 返回值,
//method 被调用的方法
//args 被调用方法的对象的参数
//target 被调用目标对象
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("执行了"+target.getClass().getName()
+"的"+method.getName()+"方法,返回值为"+returnValue);
}
}
然后到Spring配置文件中去注册,并实现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"
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="logBefore" class="com.study.log.LogBefore"/>
<bean id="logAfter" class="com.study.log.LogAfter"/>
<bean id="userService" class="com.study.service.UserServiceImpl"/>
<!-- aop配置-->
<aop:config>
<!-- 切入点expression:表达式匹配要执行的方法-->
<aop:pointcut id="pointcut" expression="execution(* com.study.service.UserServiceImpl.*(..))"/>
<!-- 执行环绕-->
<aop:advisor advice-ref="logBefore" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="logAfter" pointcut-ref="pointcut"/>
</aop:config>
</beans>
测试:代理是代理的接口所以最后是调用接口里的类。只不过我们获得bean时,是获得的实现类。
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
UserService userService = context.getBean("userService", UserService.class);
userService.add();
}
}
第二种方式:自定义类来实现Aop
写自己的切入类:方法名对应着后面调用名
public class DiyPointcut {
public void before(){
System.out.println("=============方法执行前");
}
public void after(){
System.out.println("=============方法执行后");
}
}
去spring中配置
<!-- 注册bean-->
<bean id="diy" class="com.study.diy.DiyPointcut"/>
<bean id="logBefore" class="com.study.log.LogBefore"/>
<bean id="logAfter" class="com.study.log.LogAfter"/>
<bean id="userService" class="com.study.service.UserServiceImpl"/>
<aop:config><!-- 使用AOP的标签实现 ref表示包-->
<aop:aspect ref="diy">
<aop:pointcut id="diyPointCut" expression="execution(* com.study.service.UserServiceImpl.*(..))"/>
<aop:before pointcut-ref="diyPointCut" method="before"/>
<aop:after pointcut-ref="diyPointCut" method="after"/>
</aop:aspect>
</aop:config>
测试与上一致。
第三种:使用注解实现
编写一个注解实现的增强类
@Aspect
public class AnnotationPointcut {
@Before("execution(* com.study.service.UserServiceImpl.*(..))")
public void before(){
System.out.println("before");
}
@After("execution(* com.study.service.UserServiceImpl.*(..))")
public void after(){
System.out.println("after");
}
@Around("execution(* com.study.service.UserServiceImpl.*(..))")
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕前");
System.out.println("签名:"+joinPoint.getSignature());
Object proceed = joinPoint.proceed();
System.out.println("环绕后");
System.out.println(proceed);
}
}
在Spring配置文件中配置,注册bean,并加入支持注解的配置
<bean id="annotationPointcut" class="com.study.config.AnnotationPointcut"/>
<!-- 开启注解实现-->
<aop:aspectj-autoproxy/>
通过aop命名空间的声明自动为spring容器中那些配置@aspectJ切面的bean创建代理,织入切面。当然,spring 在内部依旧采用AnnotationAwareAspectJAutoProxyCreator进行自动代理的创建工作,但具体实现的细节已经被隐藏起来了
有一个proxy-target-class属性,默认为false,表示使用jdk动态代理织入增强,当配为时,表示使用CGLib动态代理技术织入增强。不过即使proxy-target-class设置为false,如果目标类没有声明接口,则spring将自动使用CGLib动态代理。
这里注意实现顺序,是环绕前
,然后是before
,然后是主体
,然后是after
,然后是环绕后
。之前是after
最后的。
整合mybatis
加依赖
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.16</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!-- spring相关-->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>6.1.13</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>6.1.13</version>
</dependency>
<!-- aspectJ AOP 植入器-->
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.22.1</version>
<scope>runtime</scope>
</dependency>
<!--mybatis-spring整合包 -->
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>3.0.4</version>
</dependency>
</dependencies>
<!-- 配置Maven静态资源过滤问题!-->
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
注意要用
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
而不是这个,
<dependency>-->
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>9.0.0</version>
</dependency>
mysql-connector-java与mysql-connector-j是不用的!!!!!!!!!!
第一种整合方式:
需要创建一个实体类。
<?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:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- datasource 使用spring的数据源代替mybatis的配置,-->
<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=false&useUnicode=true&characterEncoding=UTF-8&allowPublicKeyRetrieval=true"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</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/study/mapper/*.xml"/>
</bean>
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<!-- 只能使用构造器注入sqlSessionFactory注入-->
<constructor-arg index="0" ref="sqlSessionFactory"/>
<!-- <constructor-arg ref="sqlSessionFactory"/>-->
</bean>
<!-- 注入id-->
<bean id="userMapper" class="com.study.mapper.UserMapperImpl">
<property name="sqlSession" ref="sqlSession"/>
</bean>
</beans>
SqlSessionDaoSupport
继承SqlSessionDaoSupport,
package com.study.mapper;
import com.study.pojo.User;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import java.util.List;
public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper {
@Override
public List<User> selectUser() {
return getSqlSession().getMapper(UserMapper.class).selectUser();
}
}
事务
一组事务当成一个事务来做,要么成功要么失败
事务再项目开发中,十分重要,涉及到数据
正常不开启的情况下:这里我们故意把删除的sql写错。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.study.mapper.UserMapper">
<select id="selectUser" resultType="com.study.pojo.User">
select * from mybatis.user;
</select>
<insert id="addUser" parameterType="com.study.pojo.User">
insert into mybatis.user (id, name, pwd) values (#{id},#{name},#{pwd});
</insert>
<delete id="deleteUser" parameterType="int">
deletes from mybatis.user where id = #{id};
</delete>
</mapper>