代理模式常用的地方:
AOP的功能完全继承到了Spring事务管理、日志和其他各种特性的上下文中。
Authentication权限认证
Logging日志
Transctions Manager事务
Lazy Loading懒加载
Context Process上下文处理
Error Handler错误跟踪(异常捕获机制)
Cache缓存处理
分为静态代理、动态代理
JDK 动态代理:
CGLib 动态代理:
cglib.jar (全称 Code Generation Library 代码生成库)
asm.jar(全称 assembly,装配)
代理的特点:
1、执行者、被代理人
2、对于被代理人来说,这件事情是一定要做的,但是我自己又不想做或者没有时间做,找代理。
3、需要获取到被代理的人个人资料。
穷举法:
租房中介:中介和你
火车票黄牛:黄牛和你
媒人:媒婆和你
明星经纪人:经纪人和明星
刘德华要开演唱会(长沙)、准备工作和善后工作
快递:
总结:做了一件什么事情呢?
字节码重组
可以做一件什么事情?
可以在每一个方法调用之前加一些代码,在方法调用之后再加一些代码
AOP:事务代理(声明式事务,哪个方法需要加事务,哪个方法不需要加事务)
日志监听
service 方法
开启一个事务(open)
事务的执行(是由我们自己的代码完成的)
监听到是否有异常,可能需要根据异常的类型来决定这个事务是否要回滚还是继续提交
(commit/rollback)
事务要关闭(close)
代理的原理
1、拿到被代理对象的引用,然后获取它的接口;
2、JDK代理重新生成一个类,同时实现我们给的代理对象所实现的接口。
3、把被代理对象的引用也拿到了
4、重新动态生成一个class字节码
5、然后编译
JDK代理与cglib代理
JDK代理:实现自InvocationHandler接口,实现代理
cglib代理:实现自MyMethodInterceptor接口,实现代理
JDK的动态动力是通过接口来进行强制转换的
生成以后的代理对象,可以强制转换为接口
CGLib的动态代理是通过生成一个被代理对象的子类,然后重写父类的方法,
生成以后的对象,可以强制转换为被代理对象(也就是用自己写的类),
子类引用赋值给父类。
cglib new出来以后的对象,是被代理对象的子类(继承课我们自己写的那个类),
OOP,在new子类之前,实际上默认先调用了我们super()方法的,
new了子类的同时,必须先new出来父类,这就相当于是间接的持有了我们父类的引用。
子类重写了父类的所有的方法,
我们改变子类对象的某些属性,是可以间接的操作父类的属性的。
Cglib和jdk动态代理的区别?
1、Jdk动态代理:利用拦截器(必须实现InvocationHandler)加上反射机制生成一个代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
2、Cglib动态代理:利用ASM框架,对代理对象类生成的class文件加载进来,通过修改其字节码生成子类来处理。
什么时候用cglib什么时候用jdk动态代理?
1、目标对象生成了接口 默认用JDK动态代理
2、如果目标对象使用了接口,可以强制使用cglib
3、如果目标对象没有实现接口,必须采用cglib库,Spring会自动在JDK动态代理和cglib之间转换
JDK动态代理和cglib字节码生成的区别?
1、JDK动态代理只能对实现了接口的类生成代理,而不能针对类
2、Cglib是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,并覆盖其中方法的增强,但是因为采用的是继承,所以该类或方法最好不要生成final,对于final类或方法,是无法继承的
Spring如何选择是用JDK还是cglib?
1、当bean实现接口时,会用JDK代理模式
2、当bean没有实现接口,用cglib实现
3、可以强制使用cglib(在spring配置中加入<aop:aspectj-autoproxy proxyt-target-class=”true”/>)
cglib举例:
1、引入依赖:
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
2、创建一个被代理人的对象:
public class ZhangSanFindLove {
public void findLove(){
System.out.println("牛郎织女七夕来相会...");
}
}
3、创建一个代理人对象:
public class MyMethodInterceptor implements MethodInterceptor {
/**
* @param clazz 文件的字节码文件
* @return 具体的对象
*/
public Object getInstance(Class clazz){
//通过Enhancer对象进行代理操作
Enhancer enhancer = new Enhancer();
//设置父类
enhancer.setSuperclass(clazz);
//设置回调
enhancer.setCallback(this);
//调用Enhancer对象的创建并返回
return enhancer.create();
}
/**
* @param className 文件的全路径名称
* @return 具体的对象
*/
public Object getInstance(String className){
//通过Enhancer对象进行代理操作
Enhancer enhancer = new Enhancer();
//设置父类
try {
enhancer.setSuperclass(Class.forName(className));
} catch (ClassNotFoundException e) {
}
//设置回调
enhancer.setCallback(this);
//调用Enhancer对象的创建并返回
return enhancer.create();
}
public Object intercept(Object o, Method method, Object[] objects, MethodProxy proxy) throws Throwable {
System.out.println("我是媒婆,你得给我找个异性");
System.out.println("--------------------------");
/**
* 不能使用invoke,invoke是指向自己
* Cglib是给指定的类添加一个子类对象,所以应该指向父类节点
* 为父类自动塑造出一个子类
*/
proxy.invokeSuper(o , objects);
System.out.println("--------------------------");
System.out.println("合适,就步入婚礼的殿堂");
return null;
}
}
测试类:
public class FindLoveTest {
public static void main(String[] args) {
ZhangSanFindLove instance = (ZhangSanFindLove)new MyMethodInterceptor().getInstance("gupaoedu.vip.agent.cglib.ZhangSanFindLove");
ZhangSanFindLove instance1 = (ZhangSanFindLove)new MyMethodInterceptor().getInstance(ZhangSanFindLove.class);
instance.findLove();
instance1.findLove();
}
}
1、设计模式七大原则 单一职责原则 一个类只负责一项功能,在类或者方法(方法及其简单时)级别遵守单一职责原则 接口隔离原则 客户端不应该依赖他不需要的接口,即一个类对另一个类的依赖应该建立在最小接口之上 依赖倒置原则 高层模块不应该依赖底层模块,二者都应该依赖其抽象 抽象不应该依赖细节,细节应该依赖抽象 依赖倒置的中心思想是面向接口编程 设计理念:相对于细节的多变性,抽象的东西要稳定的多。以抽象为...
常见的设计模式分为三类:创建型、结构型、行为型 单例模式 简单工厂模式 简单工厂模式是a类想调用b类,不直接new b类,直接new出来耦合性太高,b的实例而是通过b类的实例工厂获得。如果b类的实例工厂也是由另一个工厂获得的,这种叫抽象工厂。 代理模式 就是实现相同逻辑的一个类,作为代理,代理模式使用场景分为两个方面:延迟加载功能、增强原目标对象的功能。增强原目标对象的功能可使用jdk的动态代理实...
常见的设计模式 创建型模式 单例(Singleton) Intent Implementation Ⅰ 懒汉式-线程不安全 Ⅱ 饿汉式-线程安全 Ⅲ 懒汉式-线程安全 Ⅳ 双重校验锁-线程安全 简单工厂(Simple Factory) Intent Class Diagram 工厂方法(Factory Method) Intent Class Diagram 抽象工厂(Abstract Facto...
https://www.runoob.com/design-pattern/design-pattern-tutorial.html 设计模式: 1.简单工厂模式:(静态方法) 2048小游戏,计算器 2.装饰者模式:Thread thread=new Thread(()->System.out.println()); 3.代理模式: 把real类当作proxy类的属性,进一步封装,两个类都...
目录 1.工厂模式(侧重于对象的创建) 1.1.简单工厂模式 1.2.工厂方法模式(几种实现就几个小工厂) 1.3.抽象工厂模式 1.3.1.针对多个接口合并成抽象工厂 1.3.2.然后实现各个接口的具体工厂 1.3.3.创建一个工厂创造器/生成器类,通过传递大类型信息来获取工厂 2.策略模式(侧重于行为的封装) 3.观察者模式(发布/订阅模型) 4.责任链模式(请求沿着链向下传递)...
一、单例设计模式 饿汉式: 懒汉式:...
单例模式 设计原则: 1.单一职责原则: 又称单一功能原则。所谓职责是指类变化的原因。如果一个类有 多于一个的动机被改变,那么这个类就具有多于-一个的职责。 而单一-职责原则就是指一 一个类或者模块应该有且只有一个改变的原因。 2.开放封闭原则: 是所有面向对象原则的核心。其核心的思想是:软件实体应该是可扩展,而不可修改的。 也就是说,对扩展是开放的,而对修改是封闭的。主要体现在两个方面: -对扩...
常见的设计模式 单例模式 饿汉模式 懒汉模式 懒汉模式+synchronized 懒汉模式+双重校验模式 工厂模式 简单工厂模式 工厂方法 适配器模式 类适配器模式 对象适配器模式 装饰器模式 代理模式 静态代理模式 动态代理模式 不变模式 单例模式 在某些情况下,整个程序运行过程中只允许出现类的一个实例,但又经常频繁销毁和创建的对象,尤其是一些重量级对象,此时我们只需要创建一个对象实例,比如全局...
单例模式 所谓单例模式,就是确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例,即在应用程序中只会有这个类的一个实例存在。 通常单例模式用在仅允许数据库访问对象的实例中,从而防止打开多个数据库连接,单例模式是一种常见的设计模式,在计算机系统中,线程池、缓存、日志对象、对话框、打印机、数据库操作、显卡的驱动程序常被设计成单例。 一个单例类应包括以下几点: 和普通类不同,单例类不能被直接实...
1 工厂模式 使用工厂方法或者类生成对象,而不是在代码中直接new 2 单例模式 类对象仅允许创建一个 构造方法声明为私有 3 注册模式 全局共享和交换对象 4 适配器模式 将不同的函数接口封装成统一的API,比如: 数据库适配器:mysql、mysqli、pdo 缓存适配器:file、redis、memcache 5 策略模式 将一组特定的行为和算法封装成类,以适应某些特定的上下文环境,比如首页...