面试官:讲一下spring aop
回答:AOP是指的spring中的面向切面编程,就是把一些系统的业务比如日志管理,事务管理等变成横向切面,将其跟核心业务逻辑代码分开,使代码比较简洁。等到要用到这个切面的时候,就把它织入到目标对象中成代理对象,实际上操作的是代理对象,
假如没有aop,在做日志处理的时候,我们会在每个方法中添加日志处理,比如
但大多数的日子处理代码是相同的,为了实现代码复用,我们可能把日志处理抽离成一个新的方法。但是这样我们仍然必须手动插入这些方法。
但这样两个方法就是强耦合的,假如此时我们不需要这个功能了,或者想换成其他功能,那么就必须一个个修改。通过动态代理,可以在指定位置执行对应流程。这样就可以将一些横向的功能抽离出来形成一个独立的模块,然后在指定位置插入这些功能。这样的思想,被称为面向切面编程,亦即AOP。
切面编程,就是在你项目原有的功能基础上,通过AOP去添加新的功能,这些功能是建立在原有功能的基础上的,而且原有的功能并不知道你已经添加了新的功能。
AOP的底层实现是动态代理,它涉及到的动态代理是由两种,
代理机制:
● Spring 的 AOP 的底层用到两种代理机制:
● JDK 的动态代理 :针对实现了接口的类产生代理.
● Cglib 的动态代理:针对没有实现接口的类产生代理. 应用的是底层的字节码增强的技术 生成当前类的子类对象.
JDK动态代理的例子:
JDK动态代理的一般步骤如下:
创建被代理的接口和类;
实现InvocationHandler接口,对目标接口中声明的所有方法进行统一处理;
调用Proxy的静态方法,创建代理类并生成相应的代理对象;
使用代理。
1.创建被代理的接口和类。
// 抽象主题角色
public interface HelloService {
String hello(String name);
String hi(String msg);
}
// 具体(真实)主题角色
public class HelloServiceImpl implements HelloService{
@Override
public String hello(String name) {
return "Hello " + name;
}
@Override
public String hi(String msg) {
return "Hi, " + msg;
}
}
2. 实现InvocationHandler接口,对目标接口中声明的所有方法进行统一处理;
这里是真正对目标类进行增强的地方
是通过实现InvocationHandler的invoke方法中实现功能上的增强的。
public class MyInvocationHandler implements InvocationHandler{
// 真实业务对象
private Object target;
public MyInvocationHandler(Object target){
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 增强逻辑
System.out.println("PROXY : " + proxy.getClass().getName());
// 反射调用,目标方法
Object result = method.invoke(target, args);
// 增强逻辑
System.out.println(method.getName() + " : " + result);
return result;
}
}
3.创建代理类并生成相应的代理对象
public class test{
HelloService proxy = (HelloService)Proxy.newProxyInstance(HelloService.class.getClassLoader(),
helloService.getClass().getInterfaces(), new MyInvocationHandler(helloService));
proxy.hello("rico");
proxy.hi("panda");
}