Spring框架-eight(AOP的概述)-nine(代理模式 AOP的原理)

08-【熟悉】AOP的概述

1,什么是AOP
AOP(Aspect Oriented Programing)面向切面编程。
AOP采取横向抽取机制,取代了传统的继承纵向继承体系重复性代码(性能监视、事务管理、安全检查、缓存)
Spring的AOP采用了纯Java实现,不需要专门的编译过程和类加载器,在运行期间通过动态代理的方式向目标类注入增强代码。

2,AOP应用场景说明
举例实际项目的引用场景
对程序进行增强:不修改源码的情况下.
权限校验,日志记录,性能监控,事务控制.

3,AOP的底层实现
代理机制:
Spring的AOP的底层用到两种代理机制:
JDK的动态代理 :针对实现了接口的类产生代理.
Cglib的动态代理 :针对没有实现接口的类产生代理

09【掌握】代理模式 AOP的原理

1,代理模式概述
代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.
这里使用到编程中的一个思想:不要随意去修改别人已经写好的代码或者方法,如果需改修改,可以通过代理的方式来扩展该方法

举个例子来说明代理的作用:假设我们想邀请一位明星,那么并不是直接连接明星,而是联系明星的经纪人,来达到同样的目的.明星就是一个目标对象,他只要负责活动中的节目,而其他琐碎的事情就交给他的代理人(经纪人)来解决.这就是代理思想在现实中的一个例子
在这里插入图片描述
代理模式的关键点是:代理对象与目标对象.代理对象是对目标对象的扩展,并会调用目标对象
2代理模式的分类
静态代理

动态代理
–DK动态代理
– CGLIB动态代理

3静态代理模式

使用继承实现去目标类的加强

创建Man
在这里插入图片描述

创建SuperMan
在这里插入图片描述
测试
在这里插入图片描述

使用静态代理模式(装饰者模式)

创建Spuer2Man
在这里插入图片描述
测试
在这里插入图片描述
静态代理的缺点
每一个目标对象对应一个代理对象 ,这样代码会越来越多

4,JDK动态代理

创建Person接口
在这里插入图片描述
创建Study接口
在这里插入图片描述
创建Teach接口
在这里插入图片描述
创建Student类实现Person 和Study
在这里插入图片描述
创建Teacher类实现Person 和Teach
在这里插入图片描述
创建ProxyFactory

扫描二维码关注公众号,回复: 5469438 查看本文章
/**
 * 代理工厂
 * @author LJH
 *
 */
public class ProxyFactory {

	private Object target;//目标对象


	/**
	 * 代理工厂构造器  要传入目标对象  
	 * @param target
	 */
	public ProxyFactory(Object target) {
		super();
		this.target = target;
	}
	
	/**
	 * 得到代理对象
	 */
	public Object getProxyInstance(){
		ClassLoader loader=target.getClass().getClassLoader();//类加载器
		Class<?>[] interfaces=target.getClass().getInterfaces();//得到目标
		对象的接口数组
		//System.out.println("当前目标对象有: "+interfaces.length+" 个接口");
		InvocationHandler h=new InvocationHandler() {  //方法回调      
	//	目标方法增加    执行目标方法
			/**
			 * @param proxy  代理对象
			 * @param method  目标对象要执行的方法对象
			 * @param  args  目标方法的参数 
			 */
			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				before();//前置加强
				//Long start=System.currentTimeMillis();
				//执行目标方法
				Object invoke = method.invoke(target, args);
				//Long end=System.currentTimeMillis();
				//System.out.println("执行时间长:"+(end-start)+"  毫秒");
				after();//后置加载
				return invoke;
			}
		};
		return Proxy.newProxyInstance(loader, interfaces, h);
	}
	
	/**
	 * 前置增强
	 */
	public void before(){
		System.out.println("前置加强");
	}
	/**
	 * 后置增强
	 */
	public void after(){
		System.out.println("后置加强");
	}
}

测试
在这里插入图片描述
特点说明
1,JDK动态代理的目标类必须实现至少一个接口 【因为强转只能转成接口类型】
2,目标对象的自定义方法无法调【代理对象只能转成接口类型】

5,CGLIB的动态代理

1,导包
在这里插入图片描述
或者导spring-core.jar包

2,创建目标类
在这里插入图片描述

3,创建代理工厂类

/**
 * 代理工厂
 * @author LJH
 *
 */
public class ProxyFactory2{

	//目标对象
	private Object target;
	
	public ProxyFactory2(Object target ) {
		this.target=target;
	}
	
	/**
	 * 生成代理对象
	 * @return
	 */
	public Object getProxyInstance(){
		  //1.工具类
        Enhancer en = new Enhancer();
		//设置父类
        en.setSuperclass(target.getClass());  //父就是目标对象的类型
        //设置回调方法
        en.setCallback(new MethodInterceptor() {
        	/**
        	 * 方法拦截方法
        	 * @param paramObject 目标对象
        	 * @param paramMethod 被调用的方法
        	 * @param paramArrayOfObject 被调用的方法的参数
        	 * @param paramMethodProxy 生成的代理类里面的代理方法
        	 */
			@Override
			public Object intercept(Object paramObject, Method paramMethod,
					Object[] paramArrayOfObject, MethodProxy paramMethodProxy)
					throws Throwable {
				before();
				Object invoke = paramMethod.invoke(target,paramArrayOfObject);
				//执行目标方法
				after();
				return invoke;
			}
		});
        //创建对象
        return en.create();
	}
	
	
	/**
	 * 前置增强
	 */
	public void before(){
		System.out.println("前置加强");
	}
	/**
	 * 后置增强
	 */
	public void after(){
		System.out.println("后置加强");
	}
	
	
}

4,测试
在这里插入图片描述
5,说明
因为如果使用JDK的动态代理,那么目标对象必须实现一个或多个接口,如果目标类没有实现任何接口,那么就只能使用CGLIB的动态代理
cglib的动态代理使用的原理是在内存中构造一个目标对象的子类对象

猜你喜欢

转载自blog.csdn.net/qq_44013790/article/details/88359058