Spring 实现Aop除了自己的实现方式外,还封装了AspectJ供我们使用,这里主要是对Spring自身Aop实现的源码做下解析,而这两种方式之间的区别主要在于实现方式和作用时机上:
- Spring Aop 虽然底层也是通过字节码技术,但是是通过AopProxy生成新的的代理类,在运行时进行类加载,拦截代理对象的调用来实现切面增强。
- AspectJ 是通过字节码技术在原class对象里插入切面字节码,不产生新类,并且支持在编译期将切面功能插入到class文件里(需要引入AspectJ的编译器)。 至于AspectJ的更多介绍可以看这里。
Aop源码解析:
这里主要是通过ProxyFactoryBean作为切入点来看下Aop的实现思路。先列几个概念:
- advice:切面,用来封装在切入点上 增强的逻辑,比如写日志功能,校验功能
- pointCut::切入点,用来描述需要在哪里织入切面的增强逻辑。
- advisor: 将切面和切入点封装起来的类
- target:需要代理的目标类
了解这几个概念后,开始上代码,根据上面说的几个概念,我们需要创建一个target、一个advice,而advisor和pointCut是由Spring框架已经提供给我们了,我们只需要配置下就可以。
target类:
public class Target {
public void method1(){
System.out.println(">>> method1...");
}
}
advice切面类,根据你的需要的切面类型来实现不同的接口,比如前置增强(在方法前插入增强逻辑)需要实现MethodBeforeAdvice接口,后置增强逻辑需要实现AfterReturningAdvice接口,此处以MethodBeforeAdvice为例:
public class AopAdviceTest implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println(" before ...");
}
}
Spring的xml配置
<!--定义切面advise-->
<bean id="aopAdviceTest" class="com.alibaba.dubbo.demo.provider.AopAdviceTest"/>
<!--需要代理的对象target-->
<bean id="target" class="com.alibaba.dubbo.demo.provider.Target"/>
<!--定义advisor-->
<bean id="aopAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice" ref="aopAdviceTest"/>
<property name="patterns" value=".*method1.*"/>
</bean>
<bean id="aspectTargetProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="target"/>
<property name="interceptorNames">
<list>
<value>aopAdvisor</value>
</list>
</property>
</bean>
main方法里启动spring容器并获取bean,执行方法:
public static void main(String[] args) throws Exception {
System.out.println("服务启动成功....");
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-provider.xml"});//根据自己
Target target = (Target)context.getBean("aspectTargetProxy");
target.method1();
}
执行结果:
before ...
>>> method1...
下面分析下Spring是怎么实现增强逻辑的,在main方法里,我们看到是通过getBean方法获取的代理类,所以先弄清楚Spring是怎么讲Aop与IOC容器结合在一起的,回头再看下上面的xml配置,org.springframework.aop.framework.ProxyFactoryBean这个类实现了FactoryBean接口,FactoryBean和BeanFactory都是Spring容器的顶级接口,用于管理bean的。主要看下ProxyFactoryBean是怎么实现getObject方法。
public Object getObject() throws BeansException {
this.initializeAdvisorChain();
if (this.isSingleton()) {
return this.getSingletonInstance();
} else {
if (this.targetName == null) {
this.logger.warn("Using non-singleton proxies with singleton targets is often undesirable. Enable prototype proxies by setting the 'targetName' property.");
}
return this.newPrototypeInstance();
}
}
看下 initializeAdvisorChain方法主要获取配置文件里配置的interceptorNames, 通过beanFactory获取对应的bean后,将配置的advice封装成advisor后加到一个advisor的list里,initializeAdvisorChain() 入口,而advice封装成advisor是在this.addAdvisorOnChainCreation(advice, name);这一行代码里。
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
if (!this.advisorChainInitialized) {
//获取xml文件里配置的interceptorNames,可以回顾下上面的Spring配置里的interceptorNames
if (!ObjectUtils.isEmpty(this.interceptorNames)) {
if (this.beanFactory == null) {
throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) - cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
}
if (this.interceptorNames[this.interceptorNames.length - 1].endsWith("*") && this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
throw new AopConfigException("Target required after globals");
}
String[] var1 = this.interceptorNames;
int var2 = var1.length;
for(int var3 = 0; var3 < var2; ++var3) {
String name = var1[var3];
if (this.logger.isTraceEnabled()) {
this.logger.trace("Configuring advisor or advice '" + name + "'");
}
if (name.endsWith("*")) {
if (!(this.beanFactory instanceof ListableBeanFactory)) {
throw new AopConfigException("Can only use global advisors or interceptors with a ListableBeanFactory");
}
this.addGlobalAdvisor((ListableBeanFactory)this.beanFactory, name.substring(0, name.length() - "*".length()));
} else {
Object advice;
if (!this.singleton && !this.beanFactory.isSingleton(name)) {
advice = new ProxyFactoryBean.PrototypePlaceholderAdvisor(name);
} else {
advice = this.beanFactory.getBean(name);
}
this.addAdvisorOnChainCreation(advice, name);//将advice封装成advisor,并添加到一个advisor队列里
}
}
}
this.advisorChainInitialized = true;
}
}
初始化advisor后,开始生成代理类,这里会生成两种代理类,一种是基于接口的JDK自带的proxy,一种是基于继承的cglib的代理类,具体生成哪一种代理类,取决于你定义的target有没有实现接口,如果有实现了接口,则使用JDK的proxy,否则使用cglib,这里通过代码来看:
private synchronized Object getSingletonInstance() {
if (this.singletonInstance == null) {
this.targetSource = this.freshTargetSource();
if (this.autodetectInterfaces && this.getProxiedInterfaces().length == 0 && !this.isProxyTargetClass()) {
Class<?> targetClass = this.getTargetClass();
if (targetClass == null) {
throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
}
this.setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
}
super.setFrozen(this.freezeProxy);
this.singletonInstance = this.getProxy(this.createAopProxy());
}
return this.singletonInstance;
}
这里重点看最后一个方法:this.getProxy(copy.createAopProxy());
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
this.activate();
}
return this.getAopProxyFactory().createAopProxy(this);
}
这里仍然看最后一个调用 this.getAopProxyFactory().createAopProxy(this);
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
this.activate();
}
return this.getAopProxyFactory().createAopProxy(this);
}
这里this.getAopProxyFactory().createAopProxy(this); 调用的是DefaultAopProxyFactory类的createAopProxy方法:
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
return new JdkDynamicAopProxy(config);
} else {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: Either an interface or a target is required for proxy creation.");
} else {
return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
}
}
}
看到这里,可以看到如果有继承接口就返回JdkDynamicAopProxy,否则返回ObjenesisCglibAopProxy类,这是基于ProxyFactoryBean创建proxy的过程。