(十三)、AOP
软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
- 横切关注点: 跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如日志,安全,缓存,事务等等 …
- 切面 (ASPECT) : 横切关注点 被模块化 的特殊对象。即,它是一个类
- 通知 (Advice) : 切面必须要完成的工作。即,它是类中的一个方法(新增的功能)。
- 目标 (Target) : 被通知对象(接口/方法)
- 代理 (Proxy) : 向目标对象应用通知之后创建的对象(代理)
- 切入点 (PointCut) : 切面通知 执行的“地点”的定义。(在那个地方执行一群方法)
- 连接点 (JointPoint) : 与切入点匹配的执行点。(一个方法)
1.环境搭建
(1).导入一个jar包
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.4</version> </dependency>
2.方式一:使用Spring的API实现【接口实现】
(1).要求不改变原有代码增加日志
UserService接口
package Com.Jsxs.service; public interface UserService { void add(); void delete(); void update(); void query(); }
UserService接口的实现
package Com.Jsxs.service; public class UserServiceImp implements UserService{ @Override public void add() { System.out.println("忝居埃就"); } @Override public void delete() { } @Override public void update() { } @Override public void query() { } }
前日志
(1).继承接口MethodBeforeAdvice (2).重写方法 public void before(Method method, Object[] args, Object target){} (3).参数的介绍 method: 要执行目标对象的方法 args: 参数 target: 目标对象
package Com.Jsxs.log; import org.springframework.aop.MethodBeforeAdvice; import java.lang.reflect.Method; 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()+"的方法被执行了"); } }
后日志
(1).继承接口:AfterReturningAdvice (2).重写方法 public void afterReturning (3).参数的介绍 returnValue : 返回的结果
package Com.Jsxs.log; import org.springframework.aop.AfterReturningAdvice; import java.lang.reflect.Method; public class AfterLog implements AfterReturningAdvice { // @Override public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { System.out.println("执行了"+method.getName()+"方法的返回结果为:"+returnValue); } }
Spring配置
(1).添加约束: xmlns:aop="http://www.springframework.org/schema/aop" http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd (2).接口除外都要写bean <bean id="user456" class="Com.Jsxs.service.UserServiceImp"/> <bean id="log" class="Com.Jsxs.log.log"/> <bean id="alog" class="Com.Jsxs.log.AfterLog"/> (3).注册代理 (4).切入点:expression表达式===》execution(要执行的位置 *(修饰词)*(返回值)*(类名)*(方法名)*(参数)) <aop:pointcut id="pointcut" expression="execution(* Com.Jsxs.service.UserServiceImp.*(..))"/> (5).执行环绕 <aop:advisor advice-ref="log" pointcut-ref="pointcut"/> <aop:advisor advice-ref="alog" pointcut-ref="pointcut"/>
<?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="user456" class="Com.Jsxs.service.UserServiceImp"/> <bean id="log" class="Com.Jsxs.log.log"/> <bean id="alog" class="Com.Jsxs.log.AfterLog"/> <!-- 需要导入AOP的约束--> <!-- 注册代理--> <aop:config> <!-- 切入点:expression表达式===》execution(要执行的位置 *(修饰词)*(返回值)*(类名)*(方法名)*(参数)) --> <aop:pointcut id="pointcut" expression="execution(* Com.Jsxs.service.UserServiceImp.*(..))"/> <!-- 执行环绕增加--> <aop:advisor advice-ref="log" pointcut-ref="pointcut"/> <aop:advisor advice-ref="alog" pointcut-ref="pointcut"/> </aop:config> </beans>
测试
import Com.Jsxs.service.UserService; import Com.Jsxs.service.UserServiceImp; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MyTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService user =(UserService) context.getBean("user456"); user.add(); } }
3.方式二:自定义实现AOP【切面定义】
配置文件
(1).自定义切面(ASPECT): <aop:aspect ref="切面类id"> (2).切入点(PointCut) execution(* Com.Jsxs.service.UserServiceImp.*(..))某个类的所有方法--> <aop:pointcut id="point" expression="execution(*Com.Jsxs.service.UserServiceImp.*(..))"/> (3).通知(Advice) method: 执行的方法名 pointcut-ref: 在哪执行 <aop:before method="方法" pointcut-ref="切入点id"/> 前 <aop:after method="方法" pointcut-ref="切入点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" 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="user456" class="Com.Jsxs.service.UserServiceImp"/> <bean id="log" class="Com.Jsxs.log.log"/> <bean id="alog" class="Com.Jsxs.log.AfterLog"/> <bean id="diy" class="Com.Jsxs.diy.diy_font"/> <aop:config> <!-- 自定义切面--> <aop:aspect ref="diy"> <!-- 切入点 execution(* Com.Jsxs.diy.diy_font..*(..))某个类的所有方法--> <aop:pointcut id="point" expression="execution(* Com.Jsxs.service.UserServiceImp..*(..))"/> <!-- 通知点 method: 执行的方法名 pointcut-ref: 在哪执行 --> <aop:before method="front" pointcut-ref="point"/> <aop:after method="after" pointcut-ref="point"/> </aop:aspect> </aop:config> </beans>
插入类
package Com.Jsxs.diy; public class diy_font { public void front(){ System.out.println("方法执行前..."); } public void after(){ System.out.println("方法执行后"); } }
测试
import Com.Jsxs.service.UserService; import Com.Jsxs.service.UserServiceImp; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MyTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService user =(UserService) context.getBean("user456"); user.add(); } }
4.方式三: 注解实现AOP
注解类
(1). 这个面变成切面类 @Aspect (2).这个类由Spring托管,相当于创建一个bean @Component (3).设置通知,通知里面的内容要是切入点(在切入点前面) @Before("execution(* Com.Jsxs.service.UserServiceImp..*(..))") (4).设置通知,通知里面的内容要是切入点(在切入点后面) @After("execution(* Com.Jsxs.service.UserServiceImp..*(..))") (5).设置环绕 @Around("execution(* Com.Jsxs.service.UserServiceImp..*(..))") (6).扫描包 <context:component-scan base-package="Com.Jsxs"/> (7).开启proxy注解支持 <aop:aspectj-autoproxy/> (8).开启注解支持 <context:annotation-config/>
package Com.Jsxs; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; /** * 使用注解进行实现AOP的操作 */ @Aspect // 这个面变成切面类 @Component //这个类由Spring托管,相当于创建一个bean public class Annocation { @Before("execution(* Com.Jsxs.service.UserServiceImp..*(..))") //设置通知,通知里面的内容要是切入点 public void before(){ System.out.println("前-------"); } @After("execution(* Com.Jsxs.service.UserServiceImp..*(..))") public void after(){ System.out.println("后........"); } @Around("execution(* Com.Jsxs.service.UserServiceImp..*(..))") //在环绕增强中,我们可以给定一个参数,代表我们需要切入的点 public void around(ProceedingJoinPoint proceedingJoinPoint){ System.out.println("环绕前"); Signature signature = proceedingJoinPoint.getSignature(); //获取签名 System.out.println(signature); // 执行方法 try { Object proceed = proceedingJoinPoint.proceed(); } catch (Throwable throwable) { throwable.printStackTrace(); } System.out.println("环绕后"); } }
配置
<?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 https://www.springframework.org/schema/context/spring-context.xsd "> 扫描包 <context:component-scan base-package="Com.Jsxs"/> <bean id="user456" class="Com.Jsxs.service.UserServiceImp"/> <bean id="log" class="Com.Jsxs.log.log"/> <bean id="alog" class="Com.Jsxs.log.AfterLog"/> <!-- 开启注解支持--> <aop:aspectj-autoproxy/> <context:annotation-config/> </beans>
测试
import Com.Jsxs.service.UserService; import Com.Jsxs.service.UserServiceImp; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MyTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService user =(UserService) context.getBean("user456"); user.add(); } }
5.方式一和方式二的区别
- 方式一: 比较全(公司常用),但是填一个方法要写一个类
- 方式二: 简便灵活,多个方法可以添加在一个类中
- 方式三: 维护火葬场,注解一时爽
(十四)、整合Mybatis
http://mybatis.org/spring/zh/index.html
步骤:
1.导入相关jar包
- junit
- mybatis
- mysql数据库驱动
- Spring相关的
- aop植入
- mybatis-spring【新的】
2.编写配置文件
3.进行测试
1.回忆Mybatis
- 编写实体类
- 编写接口
- 编写核心配置文件
- 编写Mapper文件
- 编写工具类
- 进行测试
(1).搭建环境
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "https://mybatis.org/dtd/mybatis-3-config.dtd"> <!--configuration核心配置文件--> <configuration> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&charEncoding=UTF8"/> <property name="username" value="root"/> <property name="password" value="121788"/> </dataSource> </environment> </environments> <!-- 每一个Mapper.xml都需要在Mybatis核心配置文件中注册--> <mappers> <mapper class="Com.Jsxs.Mapper.UserMapper"/> </mappers> </configuration>
(2).编写工具类
package Com.Jsxs.Utils; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.IOException; import java.io.InputStream; // SqlSessionFactory---->sqlSession public class MybatisUtil { private static SqlSessionFactory sqlSessionFactory; static { String resource = "mybatis-config.xml"; try { // 第一步: 获取SqlSessionFactory对象 InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); } } // 既然有了sqlSessionFactory,顾名思义,我们就可以从中获得SqlSession的实列了 // sqlSession完全包含了面向数据库执行SQL命令所需要的所有方法 public static SqlSession getSqlSession(){ SqlSession sqlSession = sqlSessionFactory.openSession(); return sqlSession; } }
(3).编写接口实现文件
<?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="Com.Jsxs.Mapper.UserMapper"> <select id="selectUser" resultType="Com.Jsxs.pojo.User"> select *from mybatis.user </select> </mapper>
(4).测试
2.整合Mybatis方式一(没写工具类)
(0).配置相关的依赖包
【版本要求非常高:】
切记: spring-jdbc与spring-webmvc的版本号要一致。
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> </dependency> <!-- Spring链接数据库需要用到spring-jdbc--> <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.0.RELEASE</version> </dependency> <!-- 导入mybatis-spring依赖--> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.2</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.4</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.0.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> <version>1.18.20</version> <scope>provided</scope> </dependency> </dependencies> <build> <resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> </resources> </build>