跟踪spring aop的实现
aop核心概念介绍
-
什么是切面编程
在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面编程。 -
Aspect(切面)
什么是切面呢?切面这个词感觉还是挺抽象的,咱们可能知道点构成线,线构成面的数据话术。但是在编程语言中如何体现这个面呢?我的理解是“在程序中切面是由切入点和在切入点的表现的行为构成”。给个在spring中定义切面的例子如下:
<bean id="advice" class="com.im.sky.spring.aspect.GenericAdvice" />
<aop:config>
<aop:aspect id="aspect1" ref="advice">
<aop:pointcut id="p1" expression="execution(* com.im.sky.spring.bean.People.say(..))" />
<aop:before pointcut-ref="p1" method="before" />
</aop:aspect>
其中aop:aspect表示的就是一个切面,而aop:pointcut表示的是具体的切入点,即哪些类的哪些放到会被这个切面切到。aop:before表示的就是在切入点的哪一个位置执行什么行为。
-
crosscutting concerns(横切关注点)
在实现业务的同时,可能会在代码逻辑中加入日志、参数校验、安全检查,这些通用的操作在aop中就叫做横切关注点,因为这类代码是可以通用的,可以进行抽离,通过借助于aop,可能将此类代码和传统的业务代码就行解耦。 -
Advice
在切入点的具体实现,就称之为Advice,正如spring中定义的aop:before、aop:after处进行的行为等。 -
JoinPoint
Advice在业务代码执行时加入业务流程的点或者时机称之为JoinPoint,目前Spring只支持方法级别,但可以在方法的不同时机加入,比如调用方法之前、之后、返回之后、返回失败时。 -
Pointcut(切入点)
Pointcut可以看做是JoinPoint的一个子集,对于每一个方法都会有一些切入的时机,但是呢,你可能只想切入你关注的一些方法,这些方法称之为切入点。
Spring中的aop
aop的实现原理还是借助于动态代理实现的,而目前就是使用JDK动态代理和Cglib动态代理,当一个类实现接口时才可以使用JDK动态代理,而Cglib不受此限制。
步骤一:定义spring aop配置
<bean id="advice" class="com.im.sky.spring.aspect.GenericAdvice" />
<aop:config>
<aop:aspect id="aspect1" ref="advice">
<aop:pointcut id="p1" expression="execution(* com.im.sky.spring.bean.People.say(..))" />
<aop:before pointcut-ref="p1" method="before" />
</aop:aspect>
步骤二:定义基本类
People类
public class People {
private String name;
public void setName(String name) {
System.out.println("name:" + name);
this.name = name;
}
public void say() {
System.out.println("说人话");
}
public void cry() {
System.out.println("痛苦才会哭");
}
}
advice类
public class GenericAdvice {
public void before() {
System.out.println("before advice");
}
public void after() {
System.out.println("after advice");
}
public void iReturn() {
System.out.println("return advice");
}
public void throwsError() {
System.out.println("throws advice");
}
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("around advice for before");
Object o = pjp.proceed(pjp.getArgs());
System.out.println("around advice for after");
return o;
}
}
执行类Main
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
People people = context.getBean(People.class);
people.say();
}
}
spring中核心类:AbstractAutoProxyCreator
protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
// 构建一个代理类工厂
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
// 设置目标类,就是上面定义的People的实例(在spring配置文件中定义了一个,没有粘贴)
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
//这里是核心,内部会选择是采用JDK动态代理还是CgLib动态代理
return proxyFactory.getProxy(getProxyClassLoader());
}
proxyFactory.getProxy(ClassLoader loader)源码
public Object getProxy(ClassLoader classLoader) {
// 下面看看如何构建aop代理对象的
return createAopProxy().getProxy(classLoader);
}
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
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.");
}
// 如果目标类是接口或者本身就是一个代理类才会采用JDK动态代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// 这里内部用的就是Cglib动态代理
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
当选择具体采用哪种代理方式后,就会调用getProxy构成具体的目标类的代理类对象。
JDK动态代理构建目标类代理对象源码:
public Object getProxy(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
Cglib动态代理构建目标类代理对象源码:
public Object getProxy(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
}
try {
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
Class<?> proxySuperClass = rootClass;
if (ClassUtils.isCglibProxyClass(rootClass)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
// Validate the class, writing log messages as necessary.
validateClassIfNecessary(proxySuperClass, classLoader);
// Configure CGLIB Enhancer...
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// fixedInterceptorMap only populated at this point, after getCallbacks call above
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// Generate the proxy class and create a proxy instance.
return createProxyClassAndInstance(enhancer, callbacks);
}
catch (CodeGenerationException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
": Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (IllegalArgumentException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
": Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (Throwable ex) {
// TargetSource.getTarget() failed
throw new AopConfigException("Unexpected AOP exception", ex);
}
}
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
enhancer.setInterceptDuringConstruction(false);
enhancer.setCallbacks(callbacks);
return (this.constructorArgs != null ?
enhancer.create(this.constructorArgTypes, this.constructorArgs) :
enhancer.create());
}
怎么说呢,spring中的代码还是很庞大的,如果想仔细的了解,就debug进入跟踪一下吧,我这个写的也是很少的一部分,中间还涉及预处理等很多东西。