摘要
AOP(Aspect Oriented Programming),面向切面变成,如果说OOP面向对象是定义了程序了纵向的功能实现,那么AOP则是对OOP做了补充和完善,将公共行为的代码(横切关注点)横切织入到核心关注点中,从而降低重复代码,降低模块的耦合度。
本文概述
本博客将纵观aop,对常用到的名词做出解释及工作原理中获取代理对象做介绍。
名词介绍
一:Advice通知
拦截到方法后围绕方法调用而发生的切面行为,通知分为前置通知、后置通知、异常通知、环绕通知、异常通知等。
二:PointCut切入点
切点决定通知应该作用的需要增强方法的集合,通常在xml中会配置一个切入点表达式,获得符合表达式的方法的集合,可以由正则表达式或者方法名匹配等。
三:通知
有了切入点PointCut和通知Advice后,将他们关联起来的对象。
工作原理
类图:
类的说明:
ProxyConfig:配置基类,为子类提供数据配置。
AdvisedSupport:通知辅助类,封装了Advised的实现,将具体的Proxy代理生成交给他们的子类完成。
AspectJProxyactory:起到继承Spring和AspectJ的功能。
ProxyFactoryBean:提供了AOP功能的封装,当使用声明式配置时使用。
ProxyFactory:提供了AOP功能的封装,当编程式时使用。
一:使用ProxyFactoryBean生成AopProxy代理对象
ProxyFactoryBean的getObject是生成代理对象的入口:
getObject
getObject首先初始化通知器链,而通知器中封装了拦截器。
然后判断是否是单例模式。
Singleton和Prototype生成代理对象的方法是不一样的
public Object getObject() throws BeansException {
//初始化通知器链
initializeAdvisorChain();
if (isSingleton()) {
return getSingletonInstance();
}
else {
if (this.targetName == null) {
logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +
"Enable prototype proxies by setting the 'targetName' property.");
}
return newPrototypeInstance();
}
}
初始化通知器链 initializeAdvisorChain()
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
if (this.advisorChainInitialized) {
return;
}
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));
}
// Globals can't be last unless we specified a targetSource using the property...
if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&
this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
throw new AopConfigException("Target required after globals");
}
// Materialize interceptor chain from bean names. [ Materialize 这个英语百度了下是实例化的意思]
for (String name : this.interceptorNames) {
if (logger.isTraceEnabled()) {
logger.trace("Configuring advisor or advice '" + name + "'");
}
//如果是配置文件*结尾的,就遍历获取通知和拦截器bean和名字,最后都会执行
//addAdvisorOnChainCreation(advice, name);
if (name.endsWith(GLOBAL_SUFFIX)) {
if (!(this.beanFactory instanceof ListableBeanFactory)) {
throw new AopConfigException(
"Can only use global advisors or interceptors with a ListableBeanFactory");
}
addGlobalAdvisor((ListableBeanFactory) this.beanFactory,
name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
}
else {
// If we get here, we need to add a named interceptor.
// We must check if it's a singleton or prototype.
Object advice;
如果是单例,去beanFactory中取,若不是再新建一个
if (this.singleton || this.beanFactory.isSingleton(name)) {
// Add the real Advisor/Advice to the chain.
advice = this.beanFactory.getBean(name);
}
else {
// It's a prototype Advice or Advisor: replace with a prototype.
// Avoid unnecessary creation of prototype bean just for advisor chain initialization.
advice = new PrototypePlaceholderAdvisor(name);
}
//完成初始化通知器链
addAdvisorOnChainCreation(advice, name);
}
}
}
this.advisorChainInitialized = true;
}
getSingletonInstance()
private synchronized Object getSingletonInstance() {
if (this.singletonInstance == null) {
this.targetSource = freshTargetSource();
if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
// Rely on AOP infrastructure to tell us what interfaces to proxy.
//通过this.beanFactory.getType(this.targetBeanName);
//或者this.beanFactory.getBean(this.targetBeanName).getClass()
Class<?> targetClass = getTargetClass();
if (targetClass == null) {
throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
}
//设置代理对象的接口的集合,这个将会在jdk动态代理或者cglib的Enhancer中用到
setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
}
// Initialize the shared singleton instance.
super.setFrozen(this.freezeProxy);
//使用ProxyFactory来生成代理对象
this.singletonInstance = getProxy(createAopProxy());
}
return this.singletonInstance;
}
使用ProxyFactory生成的代理对象用到了jdk的动态代理或者cglib,入口:createAopProxy();
使用哪种方式,如果目标对象是接口使用jdk动态代理,目标对象是类使用cglib
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.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
回到getProxy(createAopProxy()),提供了两种实现,一种是jdk动态代理,一种是cglib。
getProxy(createAopProxy())
题外话:图片描述中
(https://img-blog.csdn.net/20180407194119344?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2l0aG91dF9yZWFsaXphdGlvbg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)把400修改下就可以调节水印的大小
先来看看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);
//调用jdk生成代理对象的地方
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 class [" +
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 class [" +
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);
}
}
至此,Spring AOP已经初始化通知器链获得了代理对象。