【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 
原文地址:https://www.cnblogs.com/jwnming/p/13635215.html