• 【Spring】IOC/DI、AOP底层原理


    Spring IOC/DI和动态代理AOP底层原理(底层代码实现)

    (1)Spring IOC/DI原理
    思想:反转控制,依赖注入,将对象创建和对象属性赋值的权利,从当前的代码中转移spring工厂中
    原理: 工厂设计模式+反射+配置文件
       	public class BeanFactory{
        		public Object getObject(String name){
                	//根据name获得对应的全类名(properties配置文件)
                	String className = ...;
                	Class clazz = Class.forName(className);
                	return clazz.newInstance();
        		}
        	}
    应用好处(使用): 解耦和,将对象创建和属性赋值的耦合解开
    比如开发中Service,Controller,DAO对象,连接池,事务管理器,都可以从spring工厂中获得,实现了解耦和效果
     
    (2)SpringAOP底层实现原理
    AOP思想:面向切面编程,在不修改目标代码的情况的情况下,动态为其增加额外功能。
    SpringAOP技术本质:使用了动态代理的设计模式,为目标类的代码,生成一个代理类,产生代理对象,替换目标对象接受调用
    静态代理
    ① 编码:
    	与目标对象相同的接口、有额外功能、拥有目标对象,调用目标对象的方法
    ② 代码:
    public class UserServiceProxy implements UserService{
    		private UserService userService = new UserServiceImpl();
       	 	public void regist(){
    			System.out.println("前置增强");
    			userService.regist();	//调用目标对象的方法
    			System.out.println("前置增强");
        	}
    }
    ③ 解释:
    	作用:实现了事务,日志,权限,性能代码解耦和
    	缺点:所有静态代理类,都是程序员人工编写,为每个目标类,都要书写一个代理类,代码冗余
    Jdk动态代理[基于接口的]
    动态代理:代理类是通过代码自动生成的。
    特点:
    	要求目标类必须有接口
    Object proxy = Proxy.newProxyInstance(ClassLoader,目标类的接口,增强功能类); //直接生成代理类,生成对象
    重要参数:ClassLoader: 动态字节码技术,动态生成一个类信息的byte[],借助于classloader,将byte[]转化为Class对象
    目标类接口:UserService
    public class Proxy0 implements UserService{
       	 	public void regist(){
            	//核心代码
        	}
    }
    增强功能类:书写额外功能,类似Spring的MethodInterceptor
    代理类产生过程
     
    类加载
     
    JDK动态代理的代码实现:
     	目标对象:UserServiceImpl
    额外功能增强的类:InvocationHandler
    生成代理类:Object proxy = Proxy.newProxyInstance(类加载器,目标类的接口,增强功能);
    public static void main(String[] args) {
    		//① 准备目标对象
    		final UserService us = new UserServiceImpl();
    		//② 准备额外功能(接口实现)
    		InvocationHandler handler = new InvocationHandler() {
    			/** 	proxy: 产生当前代理对象
    			 *  method: 目标对象的方法
    			 *	args: 目标对象的方法实际传入的参数
    			 */
    			@Override
    			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    				//前置额外增强代码
    				//目标对象的目标方法调用
    				Object o = method.invoke(us, args);	//相当于mi.proceed();
    				//后置额外增强代码
    				return o;
    			}
    		};
    		//③ 生成代理类,产生代理对象
    		Object proxy = Proxy.newProxyInstance(us.getClass().getClassLoader(), us.getClass().getInterfaces(), handler);
    		System.out.println(proxy.getClass().getSimpleName());
    		UserService usproxy = (UserService) proxy;
    		usproxy.regist(); //调用方法
    	}
    基于继承的静态代理:
    代理类核心要素:与目标类有相同的方法[继承目标类,覆盖父类方法]、额外功能代码、调用目标对象方法
    静态代理第二种实现:
    目标类:
    public class YellowLaodaye{
    		public void saleHouse() {
    			System.out.println("签合同,收钱,交易过程。");
    		}
    }
    代理类:
    public class $Proxy1 extends YelloLaodaye{
    		@Override
    public void saleHouse(){
    		//增添的额外功能
        		super.方法();
        	}
    }
    Cglib的动态代理:
    cglib动态代理技术: 生成基于继承的代理类,及其对象
    编码步骤:
    额外功能:InvocationHander(cglib包下)
    目标对象:目标类 target = new 目标类();
    组装生成代理类:
    		增强器: EnHancer
    			① 绑定父类:父类.class
    			② 组合额外功能:handler
    			③ 生成代理类的对象:eh.create();
    示例代码:
    		//① 目标对象
    		final YellowLaodaye yld = new YellowLaodaye();
    		//② 增强功能 
    		InvocationHandler handler = new InvocationHandler() {
    			@Override
    			public Object invoke(Object proxy, Method method, Object[] args)
    					throws Throwable {
    				//前置增强。
    				System.out.println("1. 发广告!");
    		    	System.out.println("2. 看房子!");
    		    	//调用目标对象的目标方法。
    		    	Object obj = method.invoke(yld, args);
    				return obj;
    			}
    		};
    		//③ 组装生成代理类的对象
    		Enhancer eh = new Enhancer();
    		eh.setSuperclass(YellowLaodaye.class); 	//绑定父类
    		eh.setCallback(handler); 	//绑定额外功能对象
    		Object proxy = eh.create();	//生成代理类对象
    		YellowLaodaye proxylaodaye = (YellowLaodaye) proxy;
    		proxylaodaye.saleHouse();
    总结Springaop原理(重要):
    1) 本质:(李代桃僵)为目标类,使用动态字节码技术(jdk动态代理,cglib动态代理)动态生成代理类,反射创建代理类的对象,替换原有的目标对象。
    注意:
    		① 如果目标类有接口,spring默认会使用jdk动态代理,
    		② 如果目标类没有接口,但是能够被继承(没有被final修饰),spring会自动切换使用cglib动态代理技术,
    		③ 如果目标类,没有接口且被final修饰,无法完成代理类生成。
    2) Jdk动态代理:基于接口的方式生成代理类、要求目标类必须有接口
    3) Cglib动态代理:基于继承的方式生成代理类、要求目标类必须能够被继承【不能用final修饰】
    4) 补充:动态代理性能
    	Jdk版本每次更新,都会大幅度提升Jdk动态代理性能,jdk1.8以后,Jdk动态代理性能完胜cglib 
    
  • 相关阅读:
    luogu1210 回文检测
    luogu2420 让我们异或吧
    luogu4151 最大XOR和路径
    线性基
    博弈论(扯淡)
    矩阵求逆 模板
    luogu2513 逆序对数列
    洛谷4316 绿豆蛙的归宿(DAG递推/概率dp)
    1898: [Zjoi2005]Swamp 沼泽鳄鱼
    矩阵
  • 原文地址:https://www.cnblogs.com/jwnming/p/13635215.html
Copyright © 2020-2023  润新知