springAOP原理
1、AOP原理
AOP:本质是在不改变原有业务逻辑的情况下,增加横向切面,从而增加一些额外功能。这样能减少很多冗余代码,易于维护。比如权限校验、日志、事务控制、性能监控等场景。
spring实现AOP使用的是动态代理。默认如果被代理对象没有实现接口则使用CGLB代理,如果被代理对象实现了接口就使用JDK动态代理;不过可以通过配置让spring强制使用CGLB代理。
2、JDK动态代理
JDK动态代理是通过反射机制实现的,创建的所有代理对象都会默认继承Java Proxy类,因为单继承,所以被代理对象必须实现一个或多个接口。
Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
由上面的代码创建代理对象,第一个参数是类加载器,第二个参数是被代理对象实现的接口,第三个对象可以叫做一个拦截器,代理对象调用的方法实际都是调用的InvocationHandler接口的invoke方法。
public interface InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; }
在其invoke方法中,可以拿到代理对象以及所调用的方法和参数。来看一个例子:
public class TestUserServiceImpl implements TestUserService { @Override public String sendMsg(String content) { System.out.println(content); return "1111"; } public static void main(String[] args) { TestUserServiceImpl target = new TestUserServiceImpl(); TestUserService proxy = (TestUserService) Proxy.newProxyInstance(TestUserService.class.getClassLoader(),new Class[]{TestUserService.class},new InvocationHandler(){ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("代理前"); method.invoke(target,args); System.out.println("代理后"); return "22222"; } }); System.out.println(proxy.sendMsg("test"));; } }
执行结果:
代理前
test
代理后
22222
可以看出执行proxy.sendMsg()最终调用的是invoke方法。
3、Spring 中CGLB代理原理
CGLB是基于父子类实现的,它会创建一个子类继承目标对象作为其代理对象,它会重写所有父类方法。spring使用CGLB代理时会在创建的子类中设置一个属性target,这个target就是被代理对象的普通对象。真正放入spring IOC容器中的是生成的代理对象,代理对象可以通过持有的target来调用被代理对象的普通对象。
public interface TestUserService { String sendMsg(String content); } class TestUserServiceProxy extends TestUserService{ TestUserService target;//TestUserService的普通对象 @Override public String sendMsg(String content) { ....//处理其他逻辑 target.sendMsg("xxx"); } }
这里代理对象还要继承被代理对象,主要是为了保持和被代理对象的类型一直,否则没法做类型转换。
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#i
nitializeBean
调用
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#a
pplyBeanPostProcessorsAfterInitialization
调用
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProce ssAfterInitialization(后置处理器AbstractAutoProxyCreator完成bean代理对象创建)
调用
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNec
essary
调用
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createPro xy (在这一步把委托对象的aop增强和通用拦截进行合并,最终给代理对象)
调用
org.springframework.aop.framework.DefaultAopProxyFactory#createAopProxy 调用
org.springframework.aop.framework.CglibAopProxy#getProxy(java.lang.ClassLoader
)