AOP
AOP(Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术,AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生泛型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
Aop在Spring中的作用
- 横切关注点:跨越应用程序多个模块的方法或功能。即与我们的业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如日志,安全,缓存,事务等等。。。
- 切面(ASPECT):横切关注点 被模块化的特殊对象。即 它是一个类
- 通知(Advice):切面必须要完成的工作,即 他是类中的一个方法
- 目标(target):被通知的对象
- 代理(Proxy):向目标对象应用通知之后创建的对象
- 切入点(PointCut):切面通知 执行的"地点"的定义
- 连接点(jointPoint):与切入点匹配的执行点
AOP(基于原生API)
- pom.xml文件
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.22</version>
</dependency>
- UserService
public interface UserService {
void add();
void delete();
void update();
void query();
}
- UserServiceImpl
public class UserServiceImpl implements UserService {
@Override
public void add() {
System.out.println("新增用户");
}
@Override
public void delete() {
System.out.println("删除用户");
}
@Override
public void update() {
System.out.println("修改用户");
}
@Override
public void query() {
System.out.println("查询用户");
}
}
- Log
public class Log 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()+"方法执行了!!");
}
}
- AfterLog
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("执行了"+method.getName()+"方法,结果为:"+returnValue);
}
}
- applicationContext
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 注册bean -->
<bean id="userService" class="org.example.demo01.UserServiceImpl"/>
<bean id="afterLog" class="org.example.demo01.AfterLog"/>
<bean id="log" class="org.example.demo01.Log"/>
<!--方式一 使用原生的api接口-->
<!-- 配置aop -->
<aop:config>
<!-- 配置切入点 pointcut 切入点 expression 表达式 execution(要执行的位置)-->
<!-- 切入点 要在什么地方执行你的代码-->
<aop:pointcut id="pointcut" expression="execution(* org.example.demo01.UserServiceImpl.*(..))"/>
<!-- 执行环绕增加-->
<aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
</aop:config>
</beans>
AOP(基于切面)
- 配置文件
- 配置aop
- 配置切入点
- 配置自定义切面要引用的类
- 在哪个方法配置
- 自己创建修饰的类(自定义切面)
public class DiyPointcut {
public void before(){
System.out.println("=======方法执行之前===========");
}
public void after(){
System.out.println("=======方法执行之后===========");
}
}
- applicationContext.xml
<bean id="diyPointcut" class="org.example.diy.DiyPointcut"/>
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* org.example.demo01.UserServiceImpl.*(..))"/>
<aop:aspect id="aspect" ref="diyPointcut">
<aop:before method="before" pointcut-ref="pointcut"/>
<aop:after method="after" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
通过切面aspect织入。
JDK动态代理和cglib动态代理,默认情况为false,jdk动态代理
<aop:aspectj-autoproxy proxy-target-class="false"/>
AOP(基于注解)
-
注意开启注解aop支持
<aop:aspectj-autoproxy/>
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 注册bean --> <bean id="userService" class="org.example.demo01.UserServiceImpl"/> <bean id="afterLog" class="org.example.demo01.AfterLog"/> <bean id="log" class="org.example.demo01.Log"/> <!-- 开启注解支持--> <aop:aspectj-autoproxy proxy-target-class="false"/> <bean id="annotationPointcut" class="org.example.annotation.AnnotationPointcut"/> </beans>
-
编写AnnotationPointcut类 并添加注解
@Aspect public class AnnotationPointcut { @Pointcut("execution(* org.example.demo01.UserServiceImpl.*(..))") public void pointcut(){ } @Before("pointcut()") public void before(){ System.out.println("注解执行方法前"); } @After("pointcut()") public void after(){ System.out.println("注解执行方法后"); } }
-
测试类
public class Client { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService userService = (UserService) context.getBean("userService"); userService.add(); } }
User接口见上述基于原生api部分
整合MyBatis
MyBatis-Spring参考文档
-
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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <!--Datasource 使用spring提供的数据源替换mybatis的配置 c3p0 dbcp druid 这使用spring提供的jdbc --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai"/> <property name="username" value="root"/> <property name="password" value="59421wjh"/> </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:org/example/mapper/*.xml"/> </bean> <!-- SqlSessionTemplate就是我们使用的sqlSession--> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <!-- 只能使用构造器注入sqlSession,因为它没有set方法--> <constructor-arg index="0" ref="sqlSessionFactory"/> </bean> <bean id="userMapper" class="org.example.dao.UserMapperImpl"> <property name="sessionTemplate" ref="sqlSession"/> </bean> </beans>
-
UserMapper
public interface UserMapper { // 查询所有用户 List<User> getUserList(); }
-
UserMapperImpl 因为需要在spring配置bean,所以需要接口的实现类
public class UserMapperImpl implements UserMapper{ private SqlSessionTemplate sessionTemplate; // 通过set方法设置sessionTemplate public void setSessionTemplate(SqlSessionTemplate sessionTemplate) { this.sessionTemplate = sessionTemplate; } @Override public List<User> getUserList() { UserMapper mapper = sessionTemplate.getMapper(UserMapper.class); return mapper.getUserList(); } }
-
UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="org.example.dao.UserMapper"> <select id="getUserList" resultType="user"> select * from user </select> <select id="getUserByID" parameterType="int" resultType="user"> select * from user where id = #{id} </select> <insert id="addUser" parameterType="user"> insert into user(id,name,pwd) values (#{id},#{name},#{pwd}) </insert> <insert id="addUser2" parameterType="map"> insert into user(id,name,pwd) values (#{userID},#{userName},#{userPassword}) </insert> </mapper>
-
测试类
@org.junit.Test public void test1(){ ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); UserMapper userMapper = context.getBean("userMapper", UserMapper.class); List<User> userList = userMapper.getUserList(); for (User user : userList) { System.out.println(user); } }
-
pom.xml依赖
<dependencies> <!--单元测试--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13</version> <scope>test</scope> </dependency> <!--mysql 驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <!--mybatis 包--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.2</version> </dependency> <!--spring 的 context core --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.0.RELEASE</version> </dependency> <!--Spring操作数据库的话,还需要一个spring-jdbc--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.1.9.RELEASE</version> </dependency> <!--Aop 支持--> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.4</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.8.13</version> </dependency> <!--mybatis 整合 spring 的依赖--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.2</version> </dependency> <!--setter 构造方法插件--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.10</version> </dependency> </dependencies>
- Spring整合MyBatis,可以将MyBatis配置文件中的一些数据源信息放到spring的beans配置文件中
- 配置SqlSessionFactory,同时绑定mybatis配置文件,即每个mapper接口对应的xml文件的包
- 配置SqlSessionTemplate,因为源码中没有set方法,只能通过构造器注入的方式实现
声明式事务
什么是事务
- 事务:把一组业务当成一个业务来做,要么都成功,要么都失败!
- 事务在项目开发中十分的重要,涉及到数据的一致性问题,不能马虎!
- 确保完整性和一致性
事务ACID 原则:
- 原则性
- 一致性
- 隔离性
多个业务可能操作同一个资源,防止数据损坏 - 持久性
事务一旦提交,无论系统发生什么问题,结果都不会被影响,被持久化的写到存储器中!
为什么需要事务?
- 如果不配置事务,可能存在数据提交不一致的情况下;
- 如果我们不在Spring 中去配置 声明式事务,我们就需要在代码中手动配置事务
- 事务在项目开发中十分重要,涉及到数据的一致性和完整性问题,不容马虎!
声明式事务代码
-
spring-dao.xml
<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/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- DataSource:使用Spring 的数据源 替换Mybatis 的配置 c3p0 dbcp druid 使用Spring 提供的JDBC org.springframework.jdbc.datasource. --> <!--配置数据源--> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/> <property name="username" value="root"/> <property name="password" value="123"/> </bean> <!--配置sqlSessionFactory 工厂--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <!--绑定mybatis的配置文件--> <property name="mapperLocations" value="classpath:cn/bloghut/mapper/*Mapper.xml"/> <!--配置别名--> <property name="typeAliases" value="cn.bloghut.domain.User"/> </bean> <!--SqlSessionTemplate 就是sqlSession--> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <!--只能使用构造器注入sqlSessionFactory,因为它没有 set 方法--> <constructor-arg index="0" ref="sqlSessionFactory"/> </bean> <!--==============================事务配置开始==============================--> <!--配置声明式事务--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!--结合AOP 实现事务的织入--> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!--给哪些方法配置事务--> <!--配置事务的传播特性: propagation read-only="true" 只读 --> <tx:method name="add" propagation="REQUIRED"/> <tx:method name="delete" propagation="REQUIRED"/> <tx:method name="update" propagation="REQUIRED"/> <tx:method name="find" read-only="true"/> <!--给所有方法配置事务--> <tx:method name="*" propagation="REQUIRED"/> </tx:attributes> </tx:advice> <!--配置事务切入--> <aop:config> <!--配置切入点--> <aop:pointcut id="txPointcut" expression="execution(* cn.bloghut.mapper.*.*(..))"/> <!--切入事务--> <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/> </aop:config> <!--==============================事务配置结束==============================--> </beans>
-
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:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <import resource="spring-dao.xml"/> <bean id="userMapper" class="cn.bloghut.mapper.impl.UserMapperImpl"> <property name="sqlSession" ref="sqlSession"/> </bean> </beans>
【狂神说Java】Spring5最新完整教程IDEA版通俗易懂_spring5最新完整教程idea版通俗易懂 pdf-CSDN博客
-