《Spring技术内幕》笔记-第三章 Spring AOP的实现
2015-07-11 12:47
826 查看
AOP 概述
1, AOP:Aspect-Oriented Programming:一种模块化机制,用来描述分散在对象,类或方法中的横切关注点。从关注点中分离出横切关注点是面向切面编程的核心概念。分离关注点使解决特定领域的代码从业务逻辑中独立出来,业务逻辑代码不再有对特定领域代码的调用。特定领域的问题通过切面封装,维护,这样子分散在整个应用程序的变动就可以很好的管理。
2, Adivice通知
Advice定义连接点做什么,为切面增强提供织入接口。在Spring AOP中,主要描述Spring AOP围绕方法调用而注入的切面行为。
Spring提供了更具体的通知类型,比如BeforeAdvice,AfterAdvice等。
下面以BeforeAdvice为例:
BeforeAdvice是一个标记接口(marker interface).
[/code]
具体我们看MethodBeforeAdvice接口。
[/code]
具体参数:method:目标方法的反射对象。args:方法执行参数。target:方法执行的对象。以CountingBeforeAdvice为例,该类完成统计被调用方法的次数。
[/code]
count方法通过hashMap存储Method对象和调用次数。
2,Pointcut切点
Pointcut切点决定Advice通知作用于哪个连接点,就是说通过Pointcut来定义需要增强的方法集合。
Spring以Pointcut接口为中心,实现了一系列的类。
3,Advisor通知器
Advisor通知器定义在哪个切点Pointcut使用哪个Advice。
以Advisor的实现DefaultPointcutAdvisor为例。在DefaultPointcutAdvisor中,有两个成员变量,分别是pointCut和Advice。
[/code]
成员变量和构造方法。
[/code]
[/code]
我们看到Pointcut引用的TRUE成员。这里使用的是单例(singleton,书中称为单件,感觉比较奇怪)。
查看TruePointcut
[/code]
Spring AOP的设计与实现
1,JVM的动态代理特性
JVM的动态代理有关可以参考:http://blog.csdn.net/mergades/article/details/42173893
2,Spring AOP的设计
Spring AOP的设计核心即使动态代理模式。
3,配置ProxyFactoryBean
ProxyFactoryBean是在Spring IoC环境中创建AOP应用的底层方法,Spring通过该类完成了对AOP使用的封装。ProxyFactoryBean的配置和使用如下:
-1,定义使用的通知器Advisor,这个通知器通过Bean定义,并实现了对应的切面行为。
-2,定义ProxyFactoryBean,把它作为另一个Bean来定义,它使封装AOP功能的主要类。
-3,定义target属性。
4,ProxyFactoryBean生成AOPProxy对象。
在Spring中可以同各国ProxyFactoryBean来完成对AOP的配置目标对象和切面行为。我们可以查看其对应的属性:
[/code]
ProxyFactoryBean依赖JDK的动态代理或者CGLIB提供的PROXY属性。
在该类中,getObject()方法对通知链进行初始化。并对Singleton和prototype类型的对象做出区分。
[/code]
initializeAdvisorChain()方法:
[/code]
Spring再通过该类的getSingletonInstance()方法生成对应单例的代理对象。
[/code]
getProxy()方法:
[/code]
Spring通过AopProxy接口把AOP代理对象的实现与框架有效地分开。
在getSingletonInstance()方法中,我们可以继续查看createAopProxy()方法,在该方法中:
[/code]
在ProxyCreatorSupport中,可以看到具体的代理生成,通过AopProxyFactory实现。
[/code]
构造方法:
[/code]
在AopProxy代理对象的生成时,如果目标是接口类,那么适合使用JDK来生成代理对象,否砸Spring会事项CGLIB来生成目标对象的代理对象。在此类中,具体不同的代理对象的具体生成使用不同的策略JdkDynamicAopProxy和CglibProxyFactory生成,只是DefaultAopProxyFactory对其进行了调用。
[/code]
5,JDK生成AopProxy代理对象
JDk通过JdkDynamicAopProxy类实现生成代理对象,该类实现了AopProxy接口。
getProxy()方法完全是基于JDK原生的动态代理来实现的。
[/code]
6,CGLIB生成AopProxy对象。
在Spring 4 中,已经实现ObjenesisCglibAopProxy来生成代理对象,与书中代码不同。该类实现了CglibAopProxy,我们查看其对应的getProxy方法:
[/code]
1, AOP:Aspect-Oriented Programming:一种模块化机制,用来描述分散在对象,类或方法中的横切关注点。从关注点中分离出横切关注点是面向切面编程的核心概念。分离关注点使解决特定领域的代码从业务逻辑中独立出来,业务逻辑代码不再有对特定领域代码的调用。特定领域的问题通过切面封装,维护,这样子分散在整个应用程序的变动就可以很好的管理。
2, Adivice通知
Advice定义连接点做什么,为切面增强提供织入接口。在Spring AOP中,主要描述Spring AOP围绕方法调用而注入的切面行为。
Spring提供了更具体的通知类型,比如BeforeAdvice,AfterAdvice等。
下面以BeforeAdvice为例:
BeforeAdvice是一个标记接口(marker interface).
public interface BeforeAdvice extends Advice {
}
[/code]
具体我们看MethodBeforeAdvice接口。
public interface MethodBeforeAdvice extends BeforeAdvice {
void before(Method method, Object[] args, Object target) throws Throwable;
}
[/code]
具体参数:method:目标方法的反射对象。args:方法执行参数。target:方法执行的对象。以CountingBeforeAdvice为例,该类完成统计被调用方法的次数。
public class CountingBeforeAdvie implements MethodBeforeAdvice{
public void before(Method method, Object[] args, Object target) throws Throwable{
count(method);
}
}
[/code]
count方法通过hashMap存储Method对象和调用次数。
2,Pointcut切点
Pointcut切点决定Advice通知作用于哪个连接点,就是说通过Pointcut来定义需要增强的方法集合。
Spring以Pointcut接口为中心,实现了一系列的类。
3,Advisor通知器
Advisor通知器定义在哪个切点Pointcut使用哪个Advice。
以Advisor的实现DefaultPointcutAdvisor为例。在DefaultPointcutAdvisor中,有两个成员变量,分别是pointCut和Advice。
public class DefaultPointcutAdvisor extends AbstractGenericPointcutAdvisor implements Serializable
[/code]
成员变量和构造方法。
private Pointcut pointcut = Pointcut.TRUE;
public DefaultPointcutAdvisor(Pointcut pointcut, Advice advice) {
this.pointcut = pointcut;
setAdvice(advice);
}
[/code]
public interface Pointcut {
/**
* Return the ClassFilter for this pointcut.
* @return the ClassFilter (never {@code null})
*/
ClassFilter getClassFilter();
/**
* Return the MethodMatcher for this pointcut.
* @return the MethodMatcher (never {@code null})
*/
MethodMatcher getMethodMatcher();
/**
* Canonical Pointcut instance that always matches.
*/
Pointcut TRUE = TruePointcut.INSTANCE;
}
[/code]
我们看到Pointcut引用的TRUE成员。这里使用的是单例(singleton,书中称为单件,感觉比较奇怪)。
查看TruePointcut
class TruePointcut implements Pointcut, Serializable {
public static final TruePointcut INSTANCE = new TruePointcut();
/**
* Enforce Singleton pattern.
*/
private TruePointcut() {
}
@Override
public ClassFilter getClassFilter() {
return ClassFilter.TRUE;
}
@Override
public MethodMatcher getMethodMatcher() {
return MethodMatcher.TRUE;
}
/**
* Required to support serialization. Replaces with canonical
* instance on deserialization, protecting Singleton pattern.
* Alternative to overriding {@code equals()}.
*/
private Object readResolve() {
return INSTANCE;
}
@Override
public String toString() {
return "Pointcut.TRUE";
}
}
[/code]
Spring AOP的设计与实现
1,JVM的动态代理特性
JVM的动态代理有关可以参考:http://blog.csdn.net/mergades/article/details/42173893
2,Spring AOP的设计
Spring AOP的设计核心即使动态代理模式。
3,配置ProxyFactoryBean
ProxyFactoryBean是在Spring IoC环境中创建AOP应用的底层方法,Spring通过该类完成了对AOP使用的封装。ProxyFactoryBean的配置和使用如下:
-1,定义使用的通知器Advisor,这个通知器通过Bean定义,并实现了对应的切面行为。
-2,定义ProxyFactoryBean,把它作为另一个Bean来定义,它使封装AOP功能的主要类。
-3,定义target属性。
4,ProxyFactoryBean生成AOPProxy对象。
在Spring中可以同各国ProxyFactoryBean来完成对AOP的配置目标对象和切面行为。我们可以查看其对应的属性:
public class ProxyFactoryBean extends ProxyCreatorSupport
implements FactoryBean<Object>, BeanClassLoaderAware, BeanFactoryAware {
/**
* This suffix in a value in an interceptor list indicates to expand globals.
*/
public static final String GLOBAL_SUFFIX = "*";
protected final Log logger = LogFactory.getLog(getClass());
private String[] interceptorNames;//已经定好的通知器
private String targetName;//目标对象
private boolean autodetectInterfaces = true;
private boolean singleton = true;
private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance();
private boolean freezeProxy = false;
private transient ClassLoader proxyClassLoader = ClassUtils.getDefaultClassLoader();
private transient boolean classLoaderConfigured = false;
private transient BeanFactory beanFactory;
/** Whether the advisor chain has already been initialized */
private boolean advisorChainInitialized = false;
/** If this is a singleton, the cached singleton proxy instance */
private Object singletonInstance;
[/code]
ProxyFactoryBean依赖JDK的动态代理或者CGLIB提供的PROXY属性。
在该类中,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();
}
}
[/code]
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.
//根据配置,添加调用
for (String name : this.interceptorNames) {
if (logger.isTraceEnabled()) {
logger.trace("Configuring advisor or 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;
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;
}
[/code]
Spring再通过该类的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.
Class<?> targetClass = getTargetClass();
if (targetClass == null) {
throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
}
setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
}
// Initialize the shared singleton instance.
super.setFrozen(this.freezeProxy);
this.singletonInstance = getProxy(createAopProxy());
}
return this.singletonInstance;
}
[/code]
getProxy()方法:
protected Object getProxy(AopProxy aopProxy) {
return aopProxy.getProxy(this.proxyClassLoader);
}
[/code]
Spring通过AopProxy接口把AOP代理对象的实现与框架有效地分开。
在getSingletonInstance()方法中,我们可以继续查看createAopProxy()方法,在该方法中:
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
[/code]
在ProxyCreatorSupport中,可以看到具体的代理生成,通过AopProxyFactory实现。
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
[/code]
构造方法:
public ProxyCreatorSupport() {
this.aopProxyFactory = new DefaultAopProxyFactory();
}
[/code]
在AopProxy代理对象的生成时,如果目标是接口类,那么适合使用JDK来生成代理对象,否砸Spring会事项CGLIB来生成目标对象的代理对象。在此类中,具体不同的代理对象的具体生成使用不同的策略JdkDynamicAopProxy和CglibProxyFactory生成,只是DefaultAopProxyFactory对其进行了调用。
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()) {//接口类
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
[/code]
5,JDK生成AopProxy代理对象
JDk通过JdkDynamicAopProxy类实现生成代理对象,该类实现了AopProxy接口。
getProxy()方法完全是基于JDK原生的动态代理来实现的。
@Override
public Object getProxy() {
return getProxy(ClassUtils.getDefaultClassLoader());
}
@Override
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);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
[/code]
6,CGLIB生成AopProxy对象。
在Spring 4 中,已经实现ObjenesisCglibAopProxy来生成代理对象,与书中代码不同。该类实现了CglibAopProxy,我们查看其对应的getProxy方法:
@Override
public Object getProxy(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
}
try {//advised中获取target对象
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);
// 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 UndeclaredThrowableStrategy(UndeclaredThrowableException.class));
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 (Exception ex) {
// TargetSource.getTarget() failed
throw new AopConfigException("Unexpected AOP exception", ex);
}
}
[/code]
相关文章推荐
- Java多线程之Lock的使用
- java内部类
- Java编写类似Flash的播放器
- eclipse导入java和android sdk源码,帮助文档
- 学习笔记_Java_day14—编码实战___一个注册页面的完整流程
- JAVA_基础简记
- java 中的 ==和equals
- Jvav反射机制
- JAVA基础之IO键盘输入
- springmvc之HelloWorld
- java 学习笔记
- JAVA基础之面向对象(个人学习笔记,更新修改中)
- java基础(个人学习笔记,不断修改更新中)
- 实现CodeIgniter在eclipse中的自动补全
- Java - Thinking in Java 第4章 控制执行流程
- java反射详解
- android——eclipse怎么添加图片
- java synchronized详解
- [LeetCode][Java] Substring with Concatenation of All Words
- Java RMI demo