A.代理模式

(一)定义

通过代理对象来访问目标对象就叫做代理模式,其意是在不修改原代码的情况下拓展功能。

(二)应用场景

在已有的代码上扩展功能,在原代码上添加代码会造成以下不便:
1、职责不够单一;
2、代码复用性不好;
3、不方便后期维护
此时,考虑使用代理模式。

应用场景:添加日志记录、性能统计、事务管理等。

(三)分类

分为jdk静态代理、jdk动态代理、cglib动态代理。

一、jdk静态代理

1、核心作用

通过代理对象控制对目标对象的访问,可以在调用目标方法前或目标方法之后做一些功能增强;

2、实现要求和步骤

(1)必须要有一个接口;
(2)代理类和委托类实现同一个接口;
(3)在代理类内部维护一个委托类的引用对象;
(4)在代理类中执行目标方法,并在其前后增强功能。

3、缺点

(1)必须要有接口,且委托类和代理类需实现同一个接口,会产生很多类,不便于管理;
(2)如果接口中增加方法,则委托类和代理类都要做相应的维护,不灵活。

二、jdk动态代理

1、作用

在代理工厂类,根据传入参数的不同,动态地生成代理对象;

2、缺点

要求委托类必须要有接口,不能代理没有接口的委托类。

3、实现要求和步骤

(1)委托类必须要有接口;
(2)代理工厂选择性实现InvocationHandler接口;
不需要和委托类实现同一个接口;
(3)在代理工厂内部维护一个Object类型的引用target(只声明,不赋值);
(4)以target为参数创建构造函数;
(5)通过Java.lang.reflect.Proxy这个类创建代理对象:
通过类名Proxy调用其静态方法:
newProxyInstance(
目标类的加载器,
目标类实现的接口的类型,
InvocationHandler的实例)
此处获得invocationHandler的实例的两种方法:
1)代理工厂实现invocationHandler方法,重写其invoke方法,在设置实例的地方传入this;
invoke方法中三个参数:当前代理类的对象proxy,目标类要执行的方法method,目标方法的参数args。在invoke方法中通过反射执行目标方法,并在执行目标方法前后执行增强的功能。
2)在invocationHandler实例的地方创建一个invocationHandler的匿名内部类,在匿名内部类中,重写其invoke方法,invoke方法中三个参数:当前代理类的对象proxy,目标类要执行的方法method,目标方法的参数args。在invoke方法中通过反射执行目标方法,并在执行目标方法前后执行增强的功能。

注意:InvocationHandler的实例是执行目标对象的方法时,会触发事件处理器的方法,会把当前执行目标对象的方法作为参数传入。
(6)返回代理对象。

4、代码示例

  1. public class DynamicFactory {
  2. //1、在代理工厂内维护一个object类的引用,targrt是目标对象
  3. private Object target;
  4. //2、创建有参构造函数
  5. public DynamicFactory(Object target) {
  6. super();
  7. this.target = target;
  8. }
  9. //3、创建方法获取代理对象
  10. public Object getInstance(Object target) {
  11. Object proxy = Proxy.newProxyInstance(
  12. target.getClass().getClassLoader(),
  13. target.getClass().getInterfaces(),
  14. new InvocationHandler() {
  15. @Override
  16. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  17. //执行目标方法
  18. Object result = method.invoke(target, args);
  19. //后置日志
  20. System.out.println(new Date().toString());
  21. return result;
  22. }
  23. });
  24. return proxy;
  25. }
  26. }

三、cglib动态代理

1、实现代理原理

(1)通过继承目标类,通过目标类的子类来完成功能增强。
(2)Enhancer允许为非接口类型动态创建一个代理对象,该代理对象对给定类型的子类,拦截了所有方法。
注意:
1)目标对象不能被final修饰;
2)实现cglib动态代理需要导入jar包:cglib和asm。

2、优点

代理功能强大,不要求委托类必须有接口。

3、实现要求和步骤

(1)导入jar包:cglib、asm;
(2)委托类有接口和没有接口都可以;
(3)创建代理工厂,选择性实现一个接口:MethodInterceptor;
(4)在代理工厂内部维护一个Object类型的引用(只声明,不赋值);
(5)以target作为参数构建一个有参构造函数;
(6)通过Enhancer对象创建代理对象:
1)设置一个父类作为模板,用这个父类,动态生成一个子类;
2)设置一个回调对象:MethodInterceptor的实例,在MethodInterceptor接口中所定义的interceptor方法中去执行目标的方法以及增强的功能。
此处创建MehotdInterceptor实例的两种方式:
①代理工厂实现MenthodInterceptor接口,重写interceptor方法,在设置实例的地方,传this;
interceptor第一个参数为当前代理对象,第二个参数为当前要执行的目标方法,第三个参数是当前要执行的目标参数的参数集合;
②在设置实例的地方,创建一个MethodInterceptor的匿名内部类,在匿名内部类中重写interceptor方法,在方法中执行目标方法和增强。
interceptor第一个参数为当前代理对象,第二个参数为当前要执行的目标方法,第三个参数是当前要执行的目标参数的参数集合;
(7)返回代理对象

4、代码示例

  1. public class CglibFactory {
  2. //1、维护Object的引用
  3. private Object target;
  4. //2、创造有参构造器
  5. public CglibFactory(Object target) {
  6. super();
  7. this.target = target;
  8. }
  9. //3、创建代理对象
  10. public Object getProxyInstance(){
  11. //创建enhancer对象
  12. Enhancer enhancer = new Enhancer();
  13. //将目标类设为enhancer的父类
  14. enhancer.setSuperclass(target.getClass());
  15. //设置回调对象
  16. enhancer.setCallback(new MethodInterceptor() {
  17. @Override
  18. public Object intercept(Object proxy, Method method, Object[] args, MethodProxy arg3) throws Throwable {
  19. Object result = method.invoke(target, args);
  20. System.out.println(new Date().toString());
  21. return result;
  22. }
  23. });
  24. return enhancer.create();
  25. }
  26. }

B.spring入门基础理论

一、什么是spring

1、spring是一个分层的JavaSE/EE 一站式(full-stack)轻量级开源框架;
2、轻量级:依赖资源少,销毁的资源少,需要什么资源就加载什么资源;
3、分层:特点:一站式,每一层都提供相应的解决方法

web层 service层 dao层
struts、springMVC spring jdbcTemplate、mybatis、hibernate

二、spring的由来

Spring 是java平台上的一个开源应用框架。它的第一个版本是由Rod Johnson写出来的。

三、spring的核心

spring的核心是控制反转(IOC)和面向切面编程(AOP);

四、spring的优点

1、方便解耦

spring是一个大型工厂,用于创建所有的对象,以及维护相互的依赖关系。

2、AOP编程的支持

面向切面编程:可以方便的实现对程序进行权限拦截、运行监控等功能;

3、声明时事务的支持

通过配置即可完成对事务的管理,无需手动编程;

4、方便程序的测试

通过注解方便的测试spring程序;

5、方便集成各种优秀的框架

spring内部提供了对各种优秀框架的直接支持:Hibenate、Mybatis、Quartz等;

6、降低JavaEE的API的使用难度

spring对JavaEE中比较难用的API进行了封装,使用难度大大降低。

五、spring的结构体系

1、五个核心模块

核心容器core spring-core:控制反转IOC和依赖注入DI的最基本实现
spring-beans:bean工厂,以及bean的装配
spring-context:spring的context上下文,及IOC容器
spring-expression:spring的表达式语言
面向切面编程AOP spring-aop:面向切面编程
spring-aspects:集成AspectJ
spring-instrument:提供一些类级的工具支持和ClassLoader级的实现,用于服务器;
spring-instrument-tomcat:针对tomcat的instrument的实现;
数据访问 spring-jdbc:jdbc的支持
spring-tx:事务控制
spring-orm:对象关系映射,集成orm框架
spring-oxm:对象xml的映射
spring-jms:Java消息服务
web spring-web:基础的web功能,如文件上传
spring-webmvc:mvc实现
spring-webmvc-portlet:基于portlet的mvc实现
spring-websocket:为web应用提供的高效通信工具
test spring-test:spring测试,提供junit与mock测试功能
spring-context-support:spring额外支持包
spring4新增 spring-websocket:为web应用提供高效的通信工具
```

spring-messaging:用于构建基于消息的应用程序 ``` |

注意:spring4去掉了spring3中的struts。

2、相互依赖关系

(1)核心容器core相互依赖关系

20181130代理模式 spring入门基础理论 - 图1

(2)aop模块相互依赖关系

context在包扫描时需依赖aop。
20181130代理模式 spring入门基础理论 - 图2

(3)数据库访问模块的相互依赖关系

20181130代理模式 spring入门基础理论 - 图3

(4)web模块相互依赖关系

20181130代理模式 spring入门基础理论 - 图4

(5)test模块相互依赖关系

20181130代理模式 spring入门基础理论 - 图5

(6)spring4新增模块依赖关系

20181130代理模式 spring入门基础理论 - 图6

六、spring用到的技术

dom解析、反射、单例模式和工厂模式。

七、搭建spring框架开发环境

1、基本spring框架需要的jar包

(1)日志包:commons-logging;
(2)核心包4个:core、beans、context、expression
(3)aop

2、xml方式配置spring

步骤
(1)导入jar包
(2)创建spring的xml配置文件
文件名称:applicationContext.xml;
文件位置:类路径下(classpath);
(3)配置spring的xml配置文件
1)引入约束:beans;
2)在xml配置文件中声明定义好的bean;有属性或者其他依赖,在bean结点下添加property结点;



注意:
①在一个类维护另一个类的引用时,使用其接口;在bean结点中的id名使用其接口名首字母小写;
②在一个类中维护另一个类的引用时,还需保证被引用的对象在本类中有set和get方法。
(4)测试
1)加载new ClassPathXmlApplicationContext(“xml配置文件路径”);
2)获取spring的上下文对象:applicationContext对象;
3)通过applicationContext对象调用方法getBean()获取注册的bean。