c. Cglib代理
1)静态代理和JDK代理模式都要求目标对象是实现一个接口,但是有时候目标对象只是一个单独的对象,并没有实现任何的接口,这个时候可使用目标对象子类来实现代理-这就是Cglib代理
2) Cglib代理也叫作子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能扩展,有些书也将Cglib代理归属到动态代理。
3) Cglib是一个强大的高性能的代码生成包,它可以在运行期扩展java类与实现java接口.它广泛的被许多AOP的框架使用,例如Spring AOP,实现方法拦截。
4)在AOP编程中如何选择代理模式:
1、目标对象需要实现接口,用JDK代理目标
2、对象不需要实现接口,用Cglib代理。
5) Cglib包的底层是通过使用字节码处理框架ASM来转换字节码并生成新的类。
CGLIB原理:动态生成一个要代理类的子类,子类重写要代理的类的所有不是final的方法。在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。它比使用java反射的JDK动态代理要快。
缺点:无法处理final方法
目标类:
/*** 目标类*/public class CglibDao {public void getMethod(){System.out.println("需要增强方法的主体内容");}}
创建代理类的类
/*** @author shizi 2022/1/25* 创建代理类的类*/public class CreateCglibProxy implements MethodInterceptor {/*** 聚合目标类*/private Object object;public CreateCglibProxy(Object object) {this.object = object;}/*** 获取代理对象* @return*/public Object getCglibProxy(){//创建一个cglib对象Enhancer enhancer = new Enhancer();//设置代理对象的父类即目标类enhancer.setSuperclass(object.getClass());//设置回调函数enhancer.setCallback(this);//创建代理类对象并返回return enhancer.create();}/*** 用于增强目标类的方法*/@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("cglib代理开始-----------");Object invoke = method.invoke(object, objects);System.out.println("cglib代理结束-----------");return invoke;}}
测试
public class Test {public static void main(String[] args) {//创建目标对象CglibDao cglib = new CglibDao();CreateCglibProxy createCglibProxy = new CreateCglibProxy(cglib);//获取代理对象CglibDao cglibProxy = (CglibDao)createCglibProxy.getCglibProxy();cglibProxy.getMethod();}}
总结JDK动态代理和CGLIB动态代理:
相同点:都是在内存中去创建代理对象,功能也是一样的,都是完成对目标方法的增强
不同点:
jdk代理:要求目标类必须实现一个接口,内存中创建出来的代理类也会实现相同的接口
        cglib代理:目标类不用实现接口,可以只是一个普通的类,在内存中创建出的代理类是
        目标类的子类
    总结:动态代理实际上都是用于增强目标方法,如果需要增强的类实现了接口,我们需要采用
    JDK代理,如果没有实现接口,我们采用Cglib代理!!
动态代理在以后开发中的作用:
    SpringAop(面向切面编程:底层就是通过代理模式实现的):
    模块1:
    模块2:
    模块3:
    假设某项目有很多模块,每个模块封装了不同业务逻辑,我们以后使用框架进行开发,目的可以提高开发效率,可以让开发人员只去关注核心业务,不去关注一些非核心的业务!!!
提一个需求:希望每个模块都能完成日志的收集,当任意一个模块的代码发生了异常,这个时候希望整理成日志文档,方便开发人员排错!注意:日志收集的代码不属于核心业务,日志收集的代码是每个模块都需要的SpringAop可以完成对核心模块的增强:日志收集的代码(就是需要对每个模块增强的部分)增强步骤:1、获取每个模块的目标方法<br /> 2、配置springAop的切面=====》切面(指的就是增强的过程)切面:<br /> spring会去校验核心模块中的核心类是否实现了接口,如果实现了,在底层使用jdk代理来完成<br /> 如果没有实现,用cglib代理来完成!!核心类实现了接口 invoke{日志收集的代码1通过反射机制调用目标方法日志收集的代码2<br /> }<br /> 所以说,通过这种方式,可以让非核心代码脱离核心模块,而且方便维护,易于管理!!!
d.工厂模式
简单工厂模式:https://blog.csdn.net/ShuSheng0007/article/details/86634864
核心就是通过一个工厂方法根据不同的条件生产同一类型的产品
抽象工厂模式:https://blog.csdn.net/ShuSheng0007/article/details/86644481
核心在于一个工厂方法生产一个品牌家族的系列产品
工厂方法模式:https://blog.csdn.net/ShuSheng0007/article/details/86636494
核心仍旧是如何创建同一类型产品(都实现同一个接口)的问题,只不过是通过为每一种要生产的产品配备一个工厂,就是说每个工厂只生产一种特定的产品。
简单工厂中创建产品使用反射:
简单工厂类:
public interface Factory {/*** 制作手机的方法*/Phone makePhone(String className);}
工厂类:
/*** 生产手机:通过简单工厂模式来写这个类*/public class PhoneFactory implements Factory {/*** 生产手机的* @param className* @return*/@Overridepublic Phone makePhone(String className) {if (className != null){try {//获取字节码对象Class aClass = Class.forName(className);//通过发射机制来创建手机手机实例Object obj = aClass.newInstance();if (obj instanceof Phone){return (Phone) obj;}} catch (ClassNotFoundException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();}}return null;}}
使用工厂生产产品:
/**** 需求:通过工厂获取手机实例*/public class FactoryTest {public static void main(String[] args) {//创建工厂实例Factory factory = new PhoneFactory();//获取华为实例Phone phone = factory.makePhone("com.jy.factory.phone.HuaWei");phone.make();//获取苹果实例Phone phone2 = factory.makePhone("com.jy.factory.phone.Iphone");phone2.make();}}
