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");
    }
}

这里代理对象还要继承被代理对象,主要是为了保持和被代理对象的类型一直,否则没法做类型转换。

4、spring AOP相关类的调用链

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
)

 

posted @ 2022-02-24 14:46  jingyi_up  阅读(303)  评论(0编辑  收藏  举报