什么是AOP?AOP的底层实现
1.什么是AOP
AOP(Aspect Oritented Programing) 面向切面编程。
AOP采取横向抽取机制,取代了传统的继承纵向继承体系的重复性代码(性能监视,事务管理,安全检查,缓存)。
Spring的AOP采用了纯java实现,不需要专门的编译过程和类加载器,在运行期间通过动态代理的方式向目标类注入增强代码。
2.AOP应用场景说明
对程序进行增强:不修改源码的情况下.
权限校验,日志记录,性能监控,事务控制.
3.AOP的底层实现
采取代理机制:
Spring的AOP的底层用到了两种代理机制:
JDK的动态代理:针对实现接口的类产生代理
Cglib的动态代理:针对没有实现接口的类产生代理
什么是动态代理
:代理是一种设计模式,提供了目标对目标对象的的访问方式:即是通过代理对象访问目标对象:可以再目标对象的基础上,增强额外的功能,拓展目标对象的功能。
这里用到的编程思想:不要随意去别人已经写好的代码或者方法,如需修改,可以使用代理的方式来扩展该方法
举个例子说明代理的作用:假如我们想邀请以为明星,那么并不是直接连接明星,而是联系明星的经纪人,来达到同样的目的.明星就是一个目标对象,他只要负责活动中的节目,而其他琐碎的事情就交给他的代理人(经纪人)来解决.这就是代理思想在现实中的一个例子
4.代理模式的分类
1.静态代理 —装饰者模式
2.动态代理:a .JDK的动态代理
b .Cglib的动态代理
接口:
package com.sxt.sleep;
public interface sleep {
public void sleep();
1
}
package com.sxt.eat;
public interface eat {
public void eat() ;
1
}
package com.sxt.man;
import com.sxt.eat.eat;
import com.sxt.sleep.sleep;
目标实现类:
public class Man implements eat, sleep {
@Override
public void sleep() {
// TODO Auto-generated method stub
System.out.println(“睡觉”);
}
@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println(“吃饭”);
}
}
创建代理工厂
package com.sxt.proxyFactory;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyFactory {
/**
- 目标类至少实现一个接口
- 代理对象只能强转成目标对象的接口类型
- 目标对象里面的自定义方法不能被调用
- 代理对象不需要接口,但是目标对象必须实现接口,否则不能使用JDK动态代理
*/
// 声明目标对象
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
/**
-
创建代理对象
*/
public Object newPRroxyInstance() {return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),
new InvocationHandler() {@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { before(); //执行目标方法 Object object = method.invoke(target, args); after(); return object; } });
}
/**
- 后置通知
/
protected void after() {
System.out.println(“搞一根”);
}
/* - 前置通知
*/
protected void before() {
System.out.println(“喝酒”);
}
}
注意该方法是在Proxy类中是静态方法,且接收的三个参数依次为
ClassLoader loader,:指定当前目标对象使用类加载器,获取加载器的方法是固定的
Class<?>[] interfaces,:目标对象实现的接口的类型,使用泛型方式确认类型
InvocationHandler h:事件处理,执行目标对象的方法时,会触发事件处理器的方法,会把当前执行目标对象的方法作为参数传入总结:
代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能用动态代理
总结:
代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能用动态代理
二.Cglib动态代理
Cglib代理,也叫作子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能的扩展.
JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口,如果想目标没有实现接口的类,就可以使用Cglib实现.
Cglib子类代理实现的方法
1
| | |
1.需要引入cglib的jar文件,但是Spring的核心包中已经包括了Cglib功能,所以直接引入spring-core-3.2.5.jar即可.
2.引入功能包后,就可以在内存中动态构建子类
3.代理的类不能为final,否则报错
4.目标对象的方法如果为final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法.
目标对象:没有实现任何接口
package com.sxt.man;
public class Man {
public void eat() {
System.out.println(“吃饭”);
}
public void sleep() {
System.out.println(“睡觉”);
}
public void run() {
System.out.println(“跑”);
}
}
package com.sxt.proxyFactory;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class ProxyFactory implements MethodInterceptor{
//声明目标对象
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
/**
- 构造代理对象
*/
public Object getProxyInstance() {
//工具类
Enhancer enhancer = new Enhancer();
//设置父类目标对象
enhancer.setSuperclass(target.getClass());
//设置回调
enhancer.setCallback((Callback) this);
//创建代理类及字节码
return enhancer.create();
}
/**
- 参数1:代理对象
- 参数2:目标方法
- 参数3:目标方法的参数
- 参数4:方法的代理
*/
@Override
public Object intercept(Object arg0, Method method, Object[] arg2, MethodProxy arg3) throws Throwable {
before();
//执行目标方法
Object object = method.invoke(target, arg2);
after();
return object;
}
private void after() {
System.out.println(“搞一根”);
}
private void before() {
System.out.println(“喝酒”);
}
}
总结:在Spring的AOP编程中:
如果加入容器的目标对象有实现接口,用JDK动态代理;
如果目标对象没有实现接口,用Cglib的动态代理