设计企业网站,公司做网站需准备什么材料,做特产的网站的分析,详情页设计详细教程第3章-第5节
一、知识点
动态代理、jdk动态代理、cglib动态代理、AOP、SpringAOP
二、目标 理解什么是动态代理和它的作用 学会使用JAVA进行动态代理 理解什么是AOP 学会使用AOP 理解什么是AOP的切入点
三、内容分析 重点 理解什么是动态代理和它的作用 理解什么是AO…第3章-第5节
一、知识点
动态代理、jdk动态代理、cglib动态代理、AOP、SpringAOP
二、目标 理解什么是动态代理和它的作用 学会使用JAVA进行动态代理 理解什么是AOP 学会使用AOP 理解什么是AOP的切入点
三、内容分析 重点 理解什么是动态代理和它的作用 理解什么是AOP 学会使用AOP 难点 理解什么是AOP 学会使用AOP
四、内容
1、动态代理
1.1 什么是代理
代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式即通过代理对象访问目标对象。这样做可以在目标对象实现的基础上增强额外的功能操作扩展目标对象的功能
开发系统的时候第一个版本的系统比较简陋只需要实现基本功能程序使用了一段时间后准备二开在二开的项目需求中需要对第一个版本的所有操作都做一个日志的记录以便于后续的系统维护和分析这个时候就可以用上代理了
1.2 什么是动态代理 特点字节码随用随创建随用随加 作用不修改源码对方法增强在不改变原有代码的情况下对方法进行增强 在程序运行的时候动态生成代理类进行增强操作
2、动态代理的使用
2.1 使用JDK实现动态代理 新建动态代理类实现InvocationHandler接口 public class Proxy1 implements InvocationHandler {private Object obj new Object();Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 要执行的方法传入一个对象所以需要创建一个对象method.invoke(obj);return null;}
} 使用Proxy类中的newProxyIntance方法并且被代理类至少实现一个接口否则不能用 三个参数 ClassLoader 类加载器用于加载代理对象类和被代理对象使用相同的加载器固定写法 Class[] 被代理对象实现的所有接口的字节码数组用于代理的接口固定写法 InvocationHandler 动态代理方法在执行时会调用里面的invoke方法去执行 public class Proxy1 implements InvocationHandler {private Object obj new Object();// 实现一个方法方法名可以自己定// 传入要调用的对象去调用// 调用这个方法传入要增强的对象public Object newProxyInstance(Object obj) {// 把传进来的对象赋值给成员变量给invoke使用this.obj obj;// 使用Proxy类中的newProxyIntance方法return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this);} Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 要执行的方法传入一个对象所以需要创建一个对象method.invoke(obj);return null;}
} 创建接口并实现 public interface StudentService {void queryAll();
} 调用 Proxy1 proxy1 new Proxy1();
StudentServiceImpl service new StudentServiceImpl();
// 会调用newProxyInstance返回一个新对象
StudentService service1 (StudentService) proxy1.newProxyInstance(service);
service1.queryAll(); 重写invoke方法 调用的时候会先执行newProxyInstance方法返回一个新的对象 调用方法的时候会执行invoke方法在invoke方法中执行我们调用的方法所以可以在invoke中编写我们的增强操作 Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {long start System.currentTimeMillis();method.invoke(obj);// args可以传递参数// 获取参数// int id (int)args[0];// method.invoke(obj, args);long end System.currentTimeMillis();System.out.println(end - start);return null;
}
2.2 使用cglib实现动态代理
增强的类不需要实现接口 引入包cglib !-- https://mvnrepository.com/artifact/cglib/cglib --
dependencygroupIdcglib/groupIdartifactIdcglib/artifactIdversion3.3.0/version
/dependency 封装代理类 public class Proxy02 implements MethodInterceptor {private Object obj new Object();// 调用这个方法传入要增强的对象public Object newProxyInstance(Object obj) {this.obj obj;// 字节码增强器用来为无接口的类创建代理Enhancer enhancer new Enhancer();// 设置要继承的类enhancer.setSuperclass(obj.getClass());// 动态代理方法在执行时会调用里面的invoke方法去执行enhancer.setCallback(this);// 创建代理return enhancer.create();}Overridepublic xxx {long start System.currentTimeMillis();method.invoke(obj, objects);long end System.currentTimeMillis();System.out.println(end - start);return null;}
} JDK实现动态代理的底层原理是基于反射创建出来的代理对象和目标对象是兄弟关系
cglib实现动态代理的底层原理是基于继承创建出来的代理对象和目标对象是父子关系 3、AOP
3.1 什么是AOP
AOPAspect Oriented Programming面向切面编程在不修改源代码的情况下给程序动态统一添加功能的一种技术
作用利用AOP对业务逻辑的各个部分进行隔离降低业务逻辑的耦合性提高程序的可重用型和开发效率。
优势减少重复代码提高开发效率维护方便
实现方式使用动态代理技术
基于动态代理技术来实现功能将功能功能提取出来如下图原本要写四个接口那么验证参数、日志都得在代码中写好然后再去实现业务代码比较繁琐使用切面以后将验证参数、日志等功能提取出来四个接口我们只需要通过配置就可以直接调用对应的功能让我们能够直接专注于写业务代码 3.2 AOP相关术语 目标对象(Target) 目标对象指将要被增强的对象即包含主业务逻辑的类对象。或者说是被一个或者多个切面所通知的对象。 织入(Weaving) 织入是将切面和业务逻辑对象连接起来, 并创建通知代理的过程。织入可以在编译时类加载时和运行时完成就是指将切面代码插入到目标对象的过程。 切面(Aspect) 切面是一个横切关注点的模块化一个切面能够包含同一个类型的不同增强方法比如说事务处理和日志处理可以理解为两个切面。切面由切入点和通知组成它既包含了横切逻辑的定义也包括了切入点的定义。 Spring AOP就是负责实施切面的框架它将切面所定义的横切逻辑织入到切面所指定的连接点中。 通知(Advice) 通知是指拦截到连接点之后要执行的代码包括了“around”、“before”和“after”等不同类型的通知。Spring AOP框架以拦截器来实现通知模型并维护一个以连接点为中心的拦截器链。 切入点(PointCut) 切入点是对连接点进行拦截的条件定义。切入点表达式如何和连接点匹配是AOP的核心Spring缺省使用AspectJ切入点语法。 一般认为所有的方法都可以认为是连接点但是我们并不希望在所有的方法上都添加通知而切入点的作用就是提供一组规则(使用 AspectJ pointcut expression language 来描述) 来匹配连接点给满足规则的连接点添加通知。可以理解为就是指切面具体织入的方法。 连接点(JoinPoint) 连接点JoinPoint指可以被切面织入的方法如方法的调用或特定的异常被抛出。简单来说连接点就是被拦截到的程序执行点因为Spring只支持方法类型的连接点所以在Spring中连接点就是被拦截到的方法。
3.3 AOP的使用
3.3.1 引入spring依赖
!-- https://mvnrepository.com/artifact/org.springframework/spring-context --
dependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion5.1.11.RELEASE/version
/dependency
!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --
dependencygroupIdorg.aspectj/groupIdartifactIdaspectjweaver/artifactIdversion1.9.6/version
/dependency
3.3.2 使用xml配置实现 把Bean交给spring容器管理 bean idlogService classcom.company.service.LogService/bean 使用aop:config标签表明开始AOP的配置 aop:config/aop:config 使用aop:aspect标签配置切面 id属性给切面提供一个唯一标识 ref属性指定通知(切面)类的Bean的id aop:configaop:aspect idlogAdvice reflogService
/aop:aspect
/aop:config 在aop:aspect内部使用对应标签配置通知的类型 aop:configaop:aspect idlogAdvice reflogServiceaop:before!-- 前置 --/aop:aspect
/aop:config 切入点配置 method属性用于指定logService类中哪个方法是前置通知 pointcut属性切入点指定切面具体织入的方法 aop:configaop:aspect idlogAdvice reflogServiceaop:before methodbefore pointcutexecution(* *..*.*(..))!-- 前置 --/aop:aspect
/aop:config aop:before 前置通知 aop:after 后置通知有异常也会执行 aop:after-returning 后置通知有异常不执行 aop:after-throwing 切入内容抛出异常后处理异常的逻辑 !-- XML要配置个throwing--
aop:after-throwing methodtest5 throwinge pointcutexecution(* *..UserService.*(..))/aop:after-throwing
// e这个变量名要和xml配置的throwing的值一致
public void test5(JoinPoint point, Exception e) throws Throwable {System.out.println(test5);System.out.println(e.getMessage());
} aop:around 环绕通知 // around 需要做特殊配置
public void test4(ProceedingJoinPoint point) throws Throwable {System.out.println(test4);point.proceed();System.out.println(test4结束);
} 配置表达式 pointcut属性用于指定切入点表达式该表达式指的是对业务层中哪些方法提供增强配置表达式 表达式写法访问修饰符 返回值 包名.类名.方法名(参数列表) 标准的表达式写法 public void 包名.类名.方法名() 访问修饰符可以省略 void 包名.类名.方法名() 返回值可以使用通配符表示任意返回 * 包名.类名.方法名() 包名可以使用通配符表示任意包但是有几级包就得写几个* * *.*.*.类名.方法名() 包名可以使用*..表示当前包及其子包 * *..类名.方法名() 类名和方法名都可以使用通配符 * *..*.*() 参数列表 可以直接写数据类型 基本数据类型直接写名称 如int 引用数据类型写包名.类名的方式 java.lang.String 可以使用通配符表示任意类型但是必须有参数 可以使用..表示有无参数均可有参数可以是任意类型 全通配写法 * *..*.*(..) 实际开发中切入点表达式的通常写法 * 包名.*.*(..) aop:configaop:aspect idlogAdvice reflogServiceaop:before methodbefore pointcutexecution(* *..*.*(..))/aop:before/aop:aspect
/aop:config 提取表达式 多个地方使用同一个表达式的时候可以提取表达式 // 单独配置切入点
aop:configaop:pointcut idlogPointcut expressionexecution(* *..*.*(..))/aop:aspect idlogAdvice reflogServiceaop:before methodbefore pointcut-reflogPointcut/aop:before/aop:aspect
/aop:config
3.3.3 使用注解实现 创建配置类 Configuration
ComponentScan(com.cpmpany.aop)
EnableAspectJAutoProxy // 开启注解的方式实现AOP
public class SpringConfig {} 创建切面类 使用 Aspect创建切面类 Order(int) 控制切面类的顺序 Component
Aspect
Order(1)
public class Strong {} 配置注解、关键字 excution (表达式) // 要增强的逻辑
// 第一个表示返回值*匹配所有的返回值
// 第二个表示要增强到哪个方法上
Before(execution(* com.cpmpany.aop.UserService.queryAll()))
public void start() {System.out.println(开始);
}
After(execution(* com.cpmpany.aop.UserService.queryAll()))
public void end() {System.out.println(结束);
} 测试类 public class TestAop01 {public static void main(String[] args) {ApplicationContext ctx new AnnotationConfigApplicationContext(SpringConfig.class);UserService service ctx.getBean(UserService.class);service.queryAll();}
}
4、小结
本章节中我们学了什么是动态代理、动态代理的作用、JAVA如何实现动态代理、理解了什么是SpringAOP以及SpringAOP的使用方式帮助我们去掌握Spring的知识点至此我们的Spring相关的知识点就以及学习完毕了希望大家可以自己多多动手去学习。
下一节中我们将会开始SSM的第二个部分SpringMVC的使用学习什么是SpringMVC学会如何使用SpringMVC写一个网页接口。