Spring
Spring
雏形:interface 21
理念:化简现有技术
依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>6.0.9</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>6.0.9</version>
</dependency>
特点:IoC和AOP,支持事务
IoC
控制反转
- 化主动为被动
- 不用去主动创建对象,而是被动接收对象
- 从程序员控制接口实现类转变为用户控制接口实现类的创建
- 说白了,就是一个接口有多个实现类,在下一层调用接口时,给接口设置一个
set
方法,然后我们可以根据需要的实现类new
一下之后赋给set
HelloSpring
public class Hello {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void show(){
System.out.println("Hello, " + name );
}
}
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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--bean就是java对象 , 由Spring创建和管理-->
<bean id="hello" class="com.lu.pojo.Hello">
<property name="name" value="lct"/>
</bean>
</beans>
测试
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Hello hello = (Hello) context.getBean("hello");
hello.show();
System.out.println(hello.getName());
}
IoC创建对象
- 在配置文件加载的时候,其管理的对象都已经初始化了
- 默认走无参构造
- 如果走有参构造不改为对应的形式,则会报错
对象
public class User {
private String name;
public User() {
System.out.println("User的无参构造");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void show() {
System.out.println(name);
}
}
无参构造
<?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">
<bean id="user" class="com.lu.pojo.User">
<property name="name" value="LCT"/>
</bean>
</beans>
有参构造
<?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">
<bean id="user" class="com.lu.pojo.User">
<constructor-arg index="0" value="lct"/>
</bean>
<bean id="user" class="com.lu.pojo.User">
<constructor-arg name="name" value="lct"/>
</bean>
</beans>
测试
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
User user = (User) context.getBean("user");
user.show();
}
Spring配置
给bean
起别名
<?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">
<bean id="user" class="com.lu.pojo.User">
<constructor-arg index="0" value="lct"/>
</bean>
<alias name="user" alias="uu"/>
</beans>
bean
<!--
id 是bean的标识符,要唯一,如果没有配置id,name就是默认标识符
如果配置id,又配置了name,那么name是别名
name可以设置多个别名,可以用逗号,分号,空格隔开
如果不配置id和name,可以根据applicationContext.getBean(.class)获取对象;
class是bean的全限定名=包名+类名
-->
<bean id="user" name="uu1 uu2, uu3; uu4" class="com.lu.pojo.User">
<constructor-arg index="0" value="lct"/>
</bean>
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
for (int i = 1; i <= 4; i++) {
String name = "uu" + i;
User user = (User) context.getBean(name);
user.show();
}
}
import
- 引入多个配置
<import resource="{path}/beans.xml"/>
DI依赖注入
对象
Address.java
public class Address {
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
Student.java
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class Student {
private String name;
private Address address;
private String[] books;
private List<String> hobbys;
private Map<String,String> card;
private Set<String> games;
private String wife;
private Properties info;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setAddress(Address address) {
this.address = address;
}
public void setBooks(String[] books) {
this.books = books;
}
public void setHobbys(List<String> hobbys) {
this.hobbys = hobbys;
}
public void setCard(Map<String, String> card) {
this.card = card;
}
public void setGames(Set<String> games) {
this.games = games;
}
public void setWife(String wife) {
this.wife = wife;
}
public void setInfo(Properties info) {
this.info = info;
}
public void show(){
System.out.println("name="+ name
+ ",address="+ address.getAddress()
+ ",books="
);
for (String book:books){
System.out.print("<<"+book+">>\t");
}
System.out.println("\n爱好:"+hobbys);
System.out.println("card:"+card);
System.out.println("games:"+games);
System.out.println("wife:"+wife);
System.out.println("info:"+info);
}
}
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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="addr" class="com.lu.pojo.Address">
<property name="address" value="suzhou"/>
</bean>
<bean id="student" class="com.lu.pojo.Student">
<property name="name" value="lct"/>
<property name="address" ref="addr"/>
<property name="books">
<array>
<value>西游记</value>
<value>红楼梦</value>
<value>水浒传</value>
</array>
</property>
<property name="hobbys">
<list>
<value>Play</value>
<value>Code</value>
<value>Sleep</value>
</list>
</property>
<property name="card">
<map>
<entry key="post" value="12364185610"/>
<entry key="construct" value="8946841560"/>
</map>
</property>
<property name="games">
<set>
<value>LOL</value>
<value>COC</value>
<value>GTA</value>
<value>LOL</value>
</set>
</property>
<property name="wife">
<null/>
</property>
<property name="info">
<props>
<prop key="学号">1231656</prop>
<prop key="性别">男</prop>
<prop key="姓名">lct</prop>
</props>
</property>
</bean>
</beans>
测试
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Student student = (Student) context.getBean("student");
student.show();
}
结果
命名空间注入
对象
public class User {
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
p
- 走无参构造
- 导入约束:
xmlns:p="http://www.springframework.org/schema/p"
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="com.lu.pojo.User" p:name="lct" p:age="18"/>
</beans>
c
- 走有参构造
- 导入约束:
xmlns:c="http://www.springframework.org/schema/c"
<?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: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="user" class="com.lu.pojo.User" c:name="lct" c:age="18"/>
</beans>
测试
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
User user = (User) context.getBean("user");
System.out.println(user);
}
bean作用域
Singleton
也就是只new一次对象,之后getBean的都直接获取第一次new的对象
Prototype
原型模式也就是在之后的getBean时重新new一个对象
Request
每次HTTP请求都会创建一个新的bean,bean只在request内有效
Session
一个HTTP Session一个bean
bean的自动装配
针对一个自定义对象的属性中有别的自定义对象
测试环境
public class User {
private Cat cat;
private Dog dog;
private String name;
public Cat getCat() {
return cat;
}
public Dog getDog() {
return dog;
}
public String getName() {
return name;
}
public void setCat(Cat cat) {
this.cat = cat;
}
public void setDog(Dog dog) {
this.dog = dog;
}
public void setName(String name) {
this.name = name;
}
}
public class Cat {
public void shout() {
System.out.println("miao~");
}
}
public class Dog {
public void shout() {
System.out.println("wang~");
}
}
byName
- 根据bean_id匹配属性变量名
- 会自动匹配对象中与未装配的set方法同名的bean_id
- 缺点是set方法后跟随的变量名一定要和bean_id名字相同
<?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">
<bean id="dog" class="Dog"/>
<bean id="cat" class="Cat"/>
<bean id="user" class="User" autowire="byName">
<property name="name" value="lct"/>
</bean>
</beans>
byType
- 会自动匹配对象中与未装配的set方法同类型的bean
- 缺点是类型必须唯一,如果存在两个相同类型的属性,则会报错
<?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">
<bean id="dog" class="Dog"/>
<bean id="cat" class="Cat"/>
<bean id="user" class="User" autowire="byType">
<property name="name" value="lct"/>
</bean>
</beans>
Autowired
- 导入约束
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
- 开启注解支持:
<context:annotation-config/>
- 可在属性上用,也可以在set方法上用
- 写了Autowired可以不用set方法
- 使用了Autowired的属性需要在xml中配置了bean且符合byName规范
public class User {
@Autowired
private Cat cat;
@Autowired
private Dog dog;
private String name;
public Cat getCat() {
return cat;
}
public Dog getDog() {
return dog;
}
public String getName() {
return name;
}
}
<?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/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/>
<bean id="dog" class="Dog"/>
<bean id="cat" class="Cat"/>
<bean id="user" class="User"/>
</beans>
属性值为null
@Nullable
或
@Autowired(required = false)
Qualifier
- Autowired识别失败
- 存在多个Dog类的bean且名字都有一定程度的自定义
- 则可以通过Qualifier显示定义bean_id匹配
@Autowired
@Qualifier(value = "dog22")
private Dog dog;
<bean id="dog22" class="Dog"/>
<bean id="dog2333" class="Dog"/>
Resource
没import出来,不知道为啥
测试
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
User user = (User) context.getBean("user");
user.getCat().shout();
user.getDog().shout();
}
注解开发
@Component # 配置了一个bean
@Value("lct") # 为bean的property配了值
@Repository # 配置了一个bean(dao)
@Service # 配置了一个bean(service)
@Controller # 配置了一个bean(controller)
@Scope("") # 配置bean的作用域
使用Java配置Spring
@Configuration
public class MyConfig {
@Bean
public User user() {
return new User();
}
}
@Configuration
代表它为一个配置文件@ComponentScan("")
可以扫描包@Import(.class)
添加别的配置类@Bean
代表注册了一个bean,它的id就为方法名
测试
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
User user = (User) context.getBean("user");
System.out.println(user.getName());
}
AOP

代理模式
保证真实角色操作的前提下,处理公共操作
静态代理
- 抽象角色:一般使用接口或抽象类实现(出租房屋)
- 真实角色:被代理的角色(房东,想要出租房屋,但不想处理公共事务,如看房签合同)
- 代理角色:代理真实角色并配备附属操作(想帮房东出租房屋同时处理相关的公共事务)
- 客户:访问代理对象的人(我找不到房东租房,所以找中介完成)
好处:
- 真实角色的操作更纯粹,不用关注一些公共操作
- 公共操作交给代理角色,分工明确
- 公共操作的业务发生扩展或者变化时,方便集中管理
缺点:
- 一个真实角色就会产生一个代理角色
动态代理
- 代理类是自动生成的
- 一个动态代理可以代理多个类,代理的是接口!
- 相关的类
Proxy
InvocationHandler
样例
UserService.java(抽象角色)
public interface UserService {
void add();
void delete();
void update();
void query();
}
UserServiceImpl.java(真实角色)
public class UserServiceImpl implements UserService {
@Override
public void add() {
System.out.println("add了一个用户");
}
@Override
public void delete() {
System.out.println("delete了一个用户");
}
@Override
public void update() {
System.out.println("update了一个用户");
}
@Override
public void query() {
System.out.println("query了一个用户");
}
}
ProxyInvocationHandler.java(代理角色)
public class ProxyInvocationHandler implements InvocationHandler {
private Object object;
public void setObject(Object object) {
this.object = object;
}
public Object getProxy() {
return Proxy.newProxyInstance(object.getClass().getClassLoader(),
object.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log(method.getName());
Object res = method.invoke(object, args);
return res;
}
public void log(String name) {
System.out.println("[debug] 执行了" + name + "方法");
}
}
Client.java(客户)
public class Client {
public static void main(String[] args) {
UserServiceImpl service = new UserServiceImpl();
ProxyInvocationHandler pih = new ProxyInvocationHandler();
pih.setObject(service);
UserService proxy = (UserService) pih.getProxy();
proxy.add();
proxy.delete();
proxy.update();
proxy.query();
}
}
AOP实现
依赖:
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.19</version>
<scope>runtime</scope>
</dependency>
导入约束:
xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
环境
UserService.java & UserServiceImpl.java
public interface UserService {
void add();
void delete();
void update();
void query();
}
public class UserServiceImpl implements UserService{
@Override
public void add() {
System.out.println("add");
}
@Override
public void delete() {
System.out.println("delete");
}
@Override
public void update() {
System.out.println("update");
}
@Override
public void query() {
System.out.println("query");
}
}
方式一
- 使用Spring实现
Log.java & AfterLog.java
public class Log implements MethodBeforeAdvice {
//method : 要执行的目标对象的方法
//args : 被调用的方法的参数
//target : 目标对象
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("[debug]" + target.getClass().getName() + " 的 " + method.getName() + " 方法被执行了");
}
}
public class AfterLog implements AfterReturningAdvice {
//returnValue : 返回值
//method : 被调用的方法
//args : 被调用的方法的对象的参数
//target : 被调用的目标对象
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("[debug]" + target.getClass().getName() +" 的 "+method.getName()+" 方法, " +"返回值: "+returnValue);
}
}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--注册bean-->
<bean id="userService" class="com.lu.service.UserServiceImpl"/>
<bean id="log" class="com.lu.log.Log"/>
<bean id="afterLog" class="com.lu.log.AfterLog"/>
<!--aop的配置-->
<aop:config>
<!--切入点 expression:表达式匹配要执行的方法-->
<aop:pointcut id="pointcut" expression="execution(* com.lu.service.UserServiceImpl.*(..))"/>
<!--执行环绕; advice-ref执行方法 . pointcut-ref切入点-->
<aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
</aop:config>
</beans>
方式二
- 自定义类实现AOP
DiyPointCut.java
public class DiyPointCut {
public void before(){
System.out.println("---------方法执行前---------");
}
public void after(){
System.out.println("---------方法执行后---------");
}
}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--注册bean-->
<bean id="userService" class="com.lu.service.UserServiceImpl"/>
<bean id="diy" class="com.lu.diy.DiyPointCut"/>
<!--aop的配置-->
<aop:config>
<!--第二种方式:使用AOP的标签实现-->
<aop:aspect ref="diy">
<aop:pointcut id="diypt" expression="execution(* com.lu.service.UserServiceImpl.*(..))"/>
<aop:before method="before" pointcut-ref="diypt"/>
<aop:after method="after" pointcut-ref="diypt"/>
</aop:aspect>
</aop:config>
</beans>
方式三
- 注解实现AOP
AnnotationPointCut.java
@Aspect
public class AnnotationPointCut {
@Before("execution(* com.lu.service.UserServiceImpl.*(..))")
public void before() {
System.out.println("---------方法执行前---------");
}
@After("execution(* com.lu.service.UserServiceImpl.*(..))")
public void after() {
System.out.println("---------方法执行后---------");
}
@Around("execution(* com.lu.service.UserServiceImpl.*(..))")
public void around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("环绕前");
System.out.println("签名: " + pjp.getSignature());
//执行目标方法proceed
Object proceed = pjp.proceed();
System.out.println("环绕后");
System.out.println(proceed);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--注册bean-->
<bean id="userService" class="com.lu.service.UserServiceImpl"/>
<bean id="apt" class="com.lu.diy.AnnotationPointCut"/>
<aop:aspectj-autoproxy/>
</beans>
测试
MyTest.java
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 代理类代理的是接口
UserService userService = context.getBean("userService", UserService.class);
userService.add();
userService.delete();
userService.update();
userService.query();
}
}
整合Mybatis
依赖:
<!--mybatis-->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.32</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>3.0.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
环境
User.java
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name;
private String pwd;
}
Mybatis回顾
UserMapper.java
public interface UserMapper {
List<User> selectUser();
}
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<package name="com.lu.pojo"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?autoReconnect=true&useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8"/>
<property name="username" value="root"/>
<property name="password" value="lu123"/>
</dataSource>
</environment>
</environments>
<mappers>
<package name="UserMapper.xml"/>
</mappers>
</configuration>
UserMapper.xml
<?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.lu.dao.UserMapper">
<select id="selectUser" resultType="user">
select * from mybatis.user
</select>
</mapper>
MyTest.java
@Test
public void selectUser() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = mapper.selectUser();
for (User user: userList){
System.out.println(user);
}
sqlSession.close();
}
Spring-Mybatis
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">
<!--配置数据源:数据源有非常多,可以使用第三方的,也可使使用Spring的-->
<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?autoReconnect=true&useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8"/>
<property name="username" value="root"/>
<property name="password" value="lu123"/>
</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/lu/dao/*.xml"/>
</bean>
<!--注册sqlSessionTemplate , 关联sqlSessionFactory-->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<!--利用构造器注入-->
<constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
<bean id="userMapper" class="com.lu.dao.UserMapperImpl">
<property name="sqlSession" ref="sqlSession"/>
</bean>
</beans>
UserMapperImpl.java
public class UserMapperImpl implements UserMapper{
private SqlSessionTemplate sqlSession;
public void setSqlSession(SqlSessionTemplate sqlSession) {
this.sqlSession = sqlSession;
}
@Override
public List<User> selectUser() {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
return mapper.selectUser();
}
}
SqlSessionDaoSupport
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">
<!--配置数据源:数据源有非常多,可以使用第三方的,也可使使用Spring的-->
<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?autoReconnect=true&useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8"/>
<property name="username" value="root"/>
<property name="password" value="lu123"/>
</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/lu/dao/*.xml"/>
</bean>
<bean id="userMapper" class="com.lu.dao.UserMapperSupport">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
</beans>
UserMapperSupport.java
public class UserMapperSupport extends SqlSessionDaoSupport implements UserMapper{
@Override
public List<User> selectUser() {
UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
return mapper.selectUser();
}
}
测试
MyTest.java
@Test
public void spring_mybatis() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
System.out.println(userMapper.selectUser());
}
Spring事务
声明式事务
- AOP横切到项目中,不影响原有代码
环境
UserMapper.java
public interface UserMapper {
List<User> selectUser();
void addUser(User user);
void deleteUser(int id);
}
UserMapperSupport.java
public class UserMapperSupport extends SqlSessionDaoSupport implements UserMapper{
@Override
public List<User> selectUser() {
UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
mapper.addUser(new User(6, "kk", "hh"));
mapper.deleteUser(6);
return mapper.selectUser();
}
@Override
public void addUser(User user) {
getSqlSession().getMapper(UserMapper.class).addUser(user);
}
@Override
public void deleteUser(int id) {
getSqlSession().getMapper(UserMapper.class).deleteUser(id);
}
}
未处理事务
UserMapper.xml
<?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.lu.dao.UserMapper">
<select id="selectUser" resultType="user">
select * from mybatis.user
</select>
<insert id="addUser" parameterType="user">
insert into mybatis.user values (#{id},#{name},#{pwd})
</insert>
<delete id="deleteUser" parameterType="int">
deletes from user where id = #{id}
</delete>
</mapper>
delete
语句存在问题
测试
@Test
public void spring_mybatis() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
System.out.println(userMapper.selectUser());
}
- 结果会发现,delete执行失败退出程序
- 但add却成功执行了
- 我们希望,只要流程中的一环出了问题,那其他环上的操作也不能成功
声明式事务
导入约束:
xmlns:tx="http://www.springframework.org/schema/tx"
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
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:tx="http://www.springframework.org/schema/tx"
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
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--配置数据源:数据源有非常多,可以使用第三方的,也可使使用Spring的-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://43.142.235.221:3310/mybatis?autoReconnect=true&useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8"/>
<property name="username" value="root"/>
<property name="password" value="lu123"/>
</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/lu/dao/*.xml"/>
</bean>
<bean id="userMapper" class="com.lu.dao.UserMapperSupport">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
<!--配置声明式事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="add" propagation="REQUIRED"/>
<tx:method name="delete" propagation="REQUIRED"/>
<tx:method name="update" propagation="REQUIRED"/>
<tx:method name="query" read-only="true"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* com.lu.dao.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>
</beans>
- 此时经过测试可以发现,由于delete语句出现问题,add语句同样没有生效
- 因此事务配置成功
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端