jdbcTemplate
jdbcTemplate是spring提供的一个jdbc模板类,是对jdbc的封装。
固然你也可以使用其他框架融入MyBatis、Hibernate。
GoF之署理模式
署理模式的作用
- 当一个对象须要受到掩护的时间,可以使用署理对象去完成某个举动。
- 须要给某个对象举行功能加强的时间,可以找一个署理举行加强。
- A对象和B对象无法直接交互时,也可以使用署理模式来完成。
署理模式中的三个脚色:
假如使用署理模式的话,客户端步伐是无法察觉的,客户端在使用署理对象的时间就像在使用目的对象。
署理模式分为静态署理和动态署理。
静态署理
目的对象类:- // 目标对象
- public class OrderServiceImpl implements OrderService{
- @Override
- public void generateOrder() {
- <?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"
- 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/context http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd" >
- <context:component-scan base-package="com.ali.service" />
- <aop:aspectj-autoproxy proxy-target-/>
- </beans>System.out.println("生成订单");
- }
- @Override
- public void modifyOrder() {
- <?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"
- 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/context http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd" >
- <context:component-scan base-package="com.ali.service" />
- <aop:aspectj-autoproxy proxy-target-/>
- </beans>System.out.println("修改订单");
- }
- @Override
- public void detailOrder() {
- <?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"
- 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/context http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd" >
- <context:component-scan base-package="com.ali.service" />
- <aop:aspectj-autoproxy proxy-target-/>
- </beans>System.out.println("查看订单详情");
- }
- }
复制代码 署理对象类:公共接口:- // 订单服务接口
- // 目标对象和代理对象的公共接口
- public interface OrderService {
- // 生成订单
- void generateOrder();
- // 修改订单
- void modifyOrder();
- // 查看订单详情
- void detailOrder();
- }
复制代码 测试:- // 实现目标对象方法执行时间的统计
- public static void main(String[] args) {
- // 创建目标对象
- OrderService orderService = new OrderServiceImpl();
- // 创建代理对象,同时将目标对象传入代理对象中
- OrderServiceProxy orderServiceProxy = new OrderServiceProxy(orderService);
- // 通过代理对象调用目标对象的方法
- orderServiceProxy.generateOrder();
- orderServiceProxy.modifyOrder();
- orderServiceProxy.detailOrder();
- }
复制代码 静态署理长处:1.办理了ocp题目 2.采取署理模式的has a。低落了耦合度。
静态署理的缺点:假设体系中有上千个接口,每个接口都须要写署理类,如许类的数量会急剧膨胀,不好维护。
那怎么办理类爆炸的题目呢?
采取动态署理。 动态署理还是署理模式,只不外是在内存中为我们动态的天生一个class字节码,这个字节码就是署理类。
动态署理
在步伐运行阶段,在内存中动态天生署理类,成为动态署理。目的是镌汰署理类的数量。
常见的动态署理技能有:JDK动态署理(只能署理接口)、CGLIB动态署理、Javassist动态署理。
JDK动态署理
公共接口 和目的对象类引用 上面的代码。Jdk动态署理不须要写署理类,jdk会在内存中自动天生署理类,因此直接在客户端代码里直接调用:
客户端代码:调用处置惩罚器类:CGLIB动态署理
既可以署理接口,也可以署理类。底层采取继承的方式实现,因此被署理的目的类不能被final修饰。
目的类:- // 目标类
- public class UserService {
- public boolean login(String username, String password) {
- <?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"
- 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/context http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd" >
- <context:component-scan base-package="com.ali.service" />
- <aop:aspectj-autoproxy proxy-target-/>
- </beans>System.out.println("用户登录,用户名:" + username + ",密码:" + password);
- <?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"
- 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/context http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd" >
- <context:component-scan base-package="com.ali.service" />
- <aop:aspectj-autoproxy proxy-target-/>
- </beans>return "admin".equals(username) && "123456".equals(password);
- }
- public void logout(String username) {
- <?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"
- 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/context http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd" >
- <context:component-scan base-package="com.ali.service" />
- <aop:aspectj-autoproxy proxy-target-/>
- </beans>System.out.println("用户退出登录,用户名:" + username);
- }
- }
复制代码 客户端代码:- public static void main(String[] args) {
- // 创建字节码增强对象
- // 这个对象是cglib的核心对象,依靠它来生成代理类
- Enhancer enhancer = new Enhancer();
- // 设置父类,也就是目标类
- enhancer.setSuperclass(UserService.class);
- // 设置回调函数(等同于jdk动态代理的中的调用处理器)
- // 在cglib中是实现方法拦截器MethodInterceptor接口
- enhancer.setCallback(new TimerMethodInterceptor());
- UserService userServiceProxy = (UserService)enhancer.create();
- boolean login = userServiceProxy.login("admin", "123456");
- System.out.println(login?"登录成功":"登录失败");
- userServiceProxy.logout("admin");
- }
复制代码 加强代码写在方法拦截器内里- public class TimerMethodInterceptor implements MethodInterceptor {
- @Override
- public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
- <?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"
- 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/context http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd" >
- <context:component-scan base-package="com.ali.service" />
- <aop:aspectj-autoproxy proxy-target-/>
- </beans>Long startTime = System.currentTimeMillis();
- <?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"
- 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/context http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd" >
- <context:component-scan base-package="com.ali.service" />
- <aop:aspectj-autoproxy proxy-target-/>
- </beans>Object o1 = methodProxy.invokeSuper(o, objects);
- <?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"
- 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/context http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd" >
- <context:component-scan base-package="com.ali.service" />
- <aop:aspectj-autoproxy proxy-target-/>
- </beans>Long endTime = System.currentTimeMillis();
- <?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"
- 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/context http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd" >
- <context:component-scan base-package="com.ali.service" />
- <aop:aspectj-autoproxy proxy-target-/>
- </beans>System.out.println("方法 " + method.getName() + " 执行耗时:" + (endTime - startTime) + "ms");
- <?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"
- 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/context http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd" >
- <context:component-scan base-package="com.ali.service" />
- <aop:aspectj-autoproxy proxy-target-/>
- </beans>return o1;
- }
- }
复制代码 留意:在jdk17环境下,cglib动态署理功能启动时会报错,须要添加启动时参数设置:
vm 参数:--add-opens java.base/java.lang=ALL-UNNAMED
program 参数:--add-opens java.base/sun.net.util=ALL-UNNAMED

面向切面编程AOP
在一个体系中一样平常会有很多体系服务,如:日志 ,变乱管理、安全等。这些服务成为交织业务。
这些交织业务是通用的。
假如在每一个业务处置惩罚过程中,都掺杂这些交织业务代码会出现2个题目:
- 交织业务代码在多个业务中反复出现。代码没有得到复用,修改这些代码会非常困难。
- 开发职员无法专业核心业务代码,在编写核心业务代码时还要处置惩罚这些交织业务代码。
这就须要使用AOP来办理以上题目。
总之,AOP就是将与核心业务无关的代码独立的抽取出来。形成一个独立的组件,然后以横向交织的方式应用到业务流程当中的过程。
aop底层使用动态署理技能实现。
spring AOP 使用的时jdk动态署理+cglib动态署理。spring 在这2种动态署理种机动切换。假如是署理接口,则使用jdk动态署理,假如署理某个类,则使用cglib。固然也可以手动设置来逼迫使用cglib。
AOP的七大术语
毗连点Joinpoint
在步伐实行流程中,可以织入切面的位置。方法的实行前后,非常抛出之后等位置。
毗连点形貌的是位置。
切点Pointcut
在步伐实行流程中,真正织入切面的方法。(一个切点对应多个毗连点)
切点形貌的是方法。
关照Advice
关照又叫加强,就是具体你要织入的的代码。
关照包罗:前置关照、后置关照、围绕关照、非常关照、终极关照。
关照形貌的是代码。
切面Aspect
切点+关照就是切面。
织入Weaving
把关照应用到目的对象上的过程。
署理对象Proxy
一个目的对象被织入关照后产生的新对象。
目的对象Target
被织入关照的对象。切点表达式
切点表达式用来界说关照(Advice)往哪些方法上切入
使用Spring的AOP
Spring对AOP的实现包罗三种方式:
- Spring连合AspectJ框架实现的AOP,基于注解方式
- Spring连合AspectJ框架实现的AOP,基于XML方式
- spring自己实现的AOP,基于xml设置方式
常用的是前2种方式。
准备工作
引入依靠- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-context</artifactId>
- <version>6.0.4</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-aspects</artifactId>
- <version>6.0.4</version>
- </dependency>
复制代码 引入定名空间(context和aop)和设置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:context="http://www.springframework.org/schema/context"
- 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/context http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd" >
- <context:component-scan base-package="com.ali.service" />
- <aop:aspectj-autoproxy proxy-target-/>
- </beans>
复制代码 编写目的类- // 目的类@Servicepublic class UserService { // 目的方法 public void login() {<?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"
- 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/context http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd" >
- <context:component-scan base-package="com.ali.service" />
- <aop:aspectj-autoproxy proxy-target-/>
- </beans>System.out.println("UserService login...."); }}
复制代码 编写切面类- // 切面类,须要@Aspect 标注@Aspect@Component("logAspect")public class LogAspect { // 切面 = 关照+切点 // 关照就是加强,就是具体要编写的加强代码 // 这里关照以方法的情势出现。 // @Before 标注的方法就是一个前置关照 @Before("execution(* com.ali.service.UserService.*(..))") public void advice( ) {<?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"
- 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/context http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd" >
- <context:component-scan base-package="com.ali.service" />
- <aop:aspectj-autoproxy proxy-target-/>
- </beans>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:context="http://www.springframework.org/schema/context"
- 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/context http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd" >
- <context:component-scan base-package="com.ali.service" />
- <aop:aspectj-autoproxy proxy-target-/>
- </beans>// 围绕关照是最大的关照,在前置关照之前,在后置关照之后 @Around("execution(* com.ali.service.UserService.*(..))") public void around(ProceedingJoinPoint joinPoint) throws Throwable {<?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"
- 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/context http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd" >
- <context:component-scan base-package="com.ali.service" />
- <aop:aspectj-autoproxy proxy-target-/>
- </beans>System.out.println("around start");<?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"
- 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/context http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd" >
- <context:component-scan base-package="com.ali.service" />
- <aop:aspectj-autoproxy proxy-target-/>
- </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"
- xmlns:context="http://www.springframework.org/schema/context"
- 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/context http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd" >
- <context:component-scan base-package="com.ali.service" />
- <aop:aspectj-autoproxy proxy-target-/>
- </beans>joinPoint.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:context="http://www.springframework.org/schema/context"
- 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/context http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd" >
- <context:component-scan base-package="com.ali.service" />
- <aop:aspectj-autoproxy proxy-target-/>
- </beans>System.out.println("around end"); }}
复制代码 测试代码:- @Test
- public void test() {
- ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
- UserService userService = context.getBean("userService", UserService.class);
- userService.login();
- }
复制代码 留意:当有多个切面类时,可以使用@Order()注解举行优先级排序,数字越小,优先级越高,就先实行。比如:@Order(2) 比@Order(3) 先实行。
在每个方法上都写一遍切点表达式很贫苦,可以界说一个通用的切点表达式,然后在方法上使用这个通用的表达式即可。- // 定义通用的切点表达式,后续通知直接使用方法名来引用切点表达式
- // 切点就是一个表达式,定义了在哪些连接点上执行通知
- @Pointcut("execution(* com.ali.service.UserService.*(..))")
- public void commmonPointcut() {
- // 这个方法只是一个标识,方法体不需要编写任何代码
- }
- @AfterReturning("commmonPointcut()")
- public void afterAdvice( ) {
- System.out.println("这是一个前置通知,方法执行前执行....");
- }
复制代码 JoinPoint的使用
关照方法可以参加参数JoinPoint,这个是spring容器自动传入的。- @Before("execution(* com.ali.service.UserService.*(..))")
- public void advice(JoinPoint joinPoint) {
- System.out.println("这是一个前置通知,方法执行前执行....");
- // 使用JoinPoint对象获取连接点的信息
- // joinPoint.getSignature() 获取连接点的方法签名
- // 通过方法签名可以获取到这个方法的具体信息
- // 获取方法名
- String methodName = joinPoint.getSignature().getName();
- System.out.println("正在执行的方法是:" + methodName);
- }
复制代码 免责声明:如果侵犯了您的权益,请联系站长及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金. |