Spring源代码分析(10)---ProxyFactoryBean(旁敲侧击的AOP时代终于来临)
2008-10-02 14:40
627 查看
我们知道,AOP是面向切面编程,在java领域的AOP中,最著名莫过于牛逼哄哄的AspectJ了,我们在前几节的源码分析中,也复习了一下动态代理的知识,在那里,我们采用了几种手段来实现切面效果以及他们之间的区别和利弊;
从这一节,我们来分析一下Spring中的Aop的实现细节;
首先,我们先来看一个Spring AOP的例子:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="name" name="name" class="org.corey.demo.Name"
abstract="false" lazy-init="default" autowire="default"
dependency-check="default">
<constructor-arg value="cui" />
<constructor-arg value="chizhou"></constructor-arg>
</bean>
<bean id="person" name="person" class="org.corey.demo.Person">
<property name="name" ref="name"></property>
</bean>
<bean name="advice" id="advice" class="org.syna.demo.BeforeAdvice"></bean>
<bean name="pointcut" id="pointcut"
class="org.springframework.aop.support.NameMatchMethodPointcut">
<property name="mappedName">
<value>*say</value>
</property>
</bean>
<bean id="advisor" name="advisor"
class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice">
<ref local="advice" />
</property>
<property name="pointcut">
<ref local="pointcut" />
</property>
</bean>
<bean name="proxyBean"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<ref local="person" />
</property>
<property name="interceptorNames">
<list>
<idref local="advisor" />
</list>
</property>
</bean>
装备:package org.syna.demo;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class BeforeAdvice implements MethodBeforeAdvice {
public void before(Method arg0, Object[] arg1, Object arg2)
throws Throwable {
System.out.println("before logging");
}
}
package org.corey.demo;
public interface IPerson {
public Name getName();
public void setName(Name name);
public void setAddress(String address);
public String getAddress();
public void say();
}
package org.corey.demo;
public class Person implements IPerson {
private String name2;
public void setBeanName(String name) {
System.out.println("set name aware");
this.name2 = name;
}
private Name name;
private String address;
public Person() {
}
public Person(Name name, String address) {
this.name = name;
this.address = address;
}
public Name getName() {
return name;
}
public void setName(Name name) {
System.out.println("set name field");
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public void say(){
System.out.println("say");
}
}
package org.syna.demo;
import org.corey.demo.IPerson;
import org.corey.demo.Person;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Demo {
/**
* @param args
*/
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext(
"applicationContext.xml");
IPerson person=(IPerson)ac.getBean("proxyBean");
person.say();
}
}
console:
set name field
before logging //这就是切面输出;
say
从上述代码,我们可见,我们主要的应用到了advice,advisor,pointcut,还有ProxyFactoryBean类,proxyFactoryBean继承于FactoryBean接口,这个接口的神奇我们在前一节就已经详细的分析过了,那么,我们就从这个接口来分析一下,我们是怎么从FactoryBean的getObject()方法取得代理对象的,以及这个代理对象是如何生成的;
![](http://p.blog.csdn.net/images/p_blog_csdn_net/turkeyzhou/EntryImages/20081002/proxyFactoryBean.png)
可见ProxyFactoryBean继承了图示中的几个接口和类,他们分别的作用是
BeanFactoryAware:BeanFactory的回调接口,可以在ProxyFactoryBean类中获取当前BeanFactory;
AdvisedSupportListener是监听ActionSupport的监听接口,是一个监听者;
FactoryBean:如同前一节所解释的;
AdvisedSupport:提供了有关这个代理的一些详细信息:比如当前代理类代理的是那一个类等等;
我们会在ProxyFactoryBean中设置如下几个属性:
1):代理类的实现的接口(可选);
public void setProxyInterfaces(String[] interfaceNames) throws ClassNotFoundException {
Class[] interfaces = AopUtils.toInterfaceArray(interfaceNames);
setInterfaces(interfaces);
}
2):advisor类的名字,从这个我们可以知道代理规则; public void setInterceptorNames(String[] interceptorNames) {
this.interceptorNames = interceptorNames;
}
3):代理类的名字;
public void setTargetName(String targetName) {
this.targetName = targetName;
}
然后我们来分析一下getObject()方法:
public Object getObject() throws BeansException {
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();
}
}
从这个方法,我们可见,ProxyBeanFactory根据上述信息给我们构造了一个PrototypeInstance();
private synchronized Object newPrototypeInstance() {
// In the case of a prototype, we need to give the proxy
// an independent instance of the configuration.
// In this case, no proxy will have an instance of this object's configuration,
// but will have an independent copy.
if (logger.isDebugEnabled()) {
logger.debug("Creating copy of prototype ProxyFactoryBean config: " + this);
}
AdvisedSupport copy = new AdvisedSupport();
// The copy needs a fresh advisor chain, and a fresh TargetSource.
TargetSource targetSource = freshTargetSource();
copy.copyConfigurationFrom(this, targetSource, freshAdvisorChain());
if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
// Rely on AOP infrastructure to tell us what interfaces to proxy.
copy.setInterfaces(ClassUtils.getAllInterfacesForClass(targetSource.getTargetClass()));
}
copy.setFrozen(this.freezeProxy);
if (logger.isDebugEnabled()) {
logger.debug("Copy has config: " + copy);
}
return getProxy(copy.createAopProxy());
}
构造proxy对象是有ProxySupport类完成的,他把这个对象委托给了一个AopProxyFactory工厂,而这个理之所有要委托给一个工厂,是因为,生成这个代理类是有选择的:
public AopProxy createAopProxy(AdvisedSupport advisedSupport) throws AopConfigException {
if (advisedSupport.isOptimize() || advisedSupport.isProxyTargetClass() ||
advisedSupport.getProxiedInterfaces().length == 0) {
if (!cglibAvailable) {
throw new AopConfigException(
"Cannot proxy target class because CGLIB2 is not available. " +
"Add CGLIB to the class path or specify proxy interfaces.");
}
return CglibProxyFactory.createCglibProxy(advisedSupport);
}
else {
return new JdkDynamicAopProxy(advisedSupport);
}
}
这里生成动态代理类有两种方式,一种是如果用户没有给被代理类实现接口,那么,就会使用cglib来生成代理类,如果制定了实现接口,那么就会使用jdk的InvocationHandler接口实现代理;
这个AopProxy类是一个Proxy Object的包装类;
public interface AopProxy {
/**
* Create a new proxy object.
* <p>Uses the most optimal default class loader (if necessary for proxy creation):
* usually, the thread context class loader.
* @see java.lang.Thread#getContextClassLoader()
*/
Object getProxy();
/**
* Create a new proxy object.
* <p>Uses the given class loader (if necessary for proxy creation).
* <code>null</code> will simply be passed down and thus lead to the low-level
* proxy facility's default, which is usually different from the default chosen
* by the AopProxy implementation's <code>getProxy</code> method.
* @param classLoader the class loader to create the proxy with
* (or <code>null</code> for the low-level proxy facility's default)
*/
Object getProxy(ClassLoader classLoader);
}
能够从中得到代理的Object;
从这一节,我们来分析一下Spring中的Aop的实现细节;
首先,我们先来看一个Spring AOP的例子:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="name" name="name" class="org.corey.demo.Name"
abstract="false" lazy-init="default" autowire="default"
dependency-check="default">
<constructor-arg value="cui" />
<constructor-arg value="chizhou"></constructor-arg>
</bean>
<bean id="person" name="person" class="org.corey.demo.Person">
<property name="name" ref="name"></property>
</bean>
<bean name="advice" id="advice" class="org.syna.demo.BeforeAdvice"></bean>
<bean name="pointcut" id="pointcut"
class="org.springframework.aop.support.NameMatchMethodPointcut">
<property name="mappedName">
<value>*say</value>
</property>
</bean>
<bean id="advisor" name="advisor"
class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice">
<ref local="advice" />
</property>
<property name="pointcut">
<ref local="pointcut" />
</property>
</bean>
<bean name="proxyBean"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<ref local="person" />
</property>
<property name="interceptorNames">
<list>
<idref local="advisor" />
</list>
</property>
</bean>
装备:package org.syna.demo;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class BeforeAdvice implements MethodBeforeAdvice {
public void before(Method arg0, Object[] arg1, Object arg2)
throws Throwable {
System.out.println("before logging");
}
}
package org.corey.demo;
public interface IPerson {
public Name getName();
public void setName(Name name);
public void setAddress(String address);
public String getAddress();
public void say();
}
package org.corey.demo;
public class Person implements IPerson {
private String name2;
public void setBeanName(String name) {
System.out.println("set name aware");
this.name2 = name;
}
private Name name;
private String address;
public Person() {
}
public Person(Name name, String address) {
this.name = name;
this.address = address;
}
public Name getName() {
return name;
}
public void setName(Name name) {
System.out.println("set name field");
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public void say(){
System.out.println("say");
}
}
package org.syna.demo;
import org.corey.demo.IPerson;
import org.corey.demo.Person;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Demo {
/**
* @param args
*/
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext(
"applicationContext.xml");
IPerson person=(IPerson)ac.getBean("proxyBean");
person.say();
}
}
console:
set name field
before logging //这就是切面输出;
say
从上述代码,我们可见,我们主要的应用到了advice,advisor,pointcut,还有ProxyFactoryBean类,proxyFactoryBean继承于FactoryBean接口,这个接口的神奇我们在前一节就已经详细的分析过了,那么,我们就从这个接口来分析一下,我们是怎么从FactoryBean的getObject()方法取得代理对象的,以及这个代理对象是如何生成的;
![](http://p.blog.csdn.net/images/p_blog_csdn_net/turkeyzhou/EntryImages/20081002/proxyFactoryBean.png)
可见ProxyFactoryBean继承了图示中的几个接口和类,他们分别的作用是
BeanFactoryAware:BeanFactory的回调接口,可以在ProxyFactoryBean类中获取当前BeanFactory;
AdvisedSupportListener是监听ActionSupport的监听接口,是一个监听者;
FactoryBean:如同前一节所解释的;
AdvisedSupport:提供了有关这个代理的一些详细信息:比如当前代理类代理的是那一个类等等;
我们会在ProxyFactoryBean中设置如下几个属性:
1):代理类的实现的接口(可选);
public void setProxyInterfaces(String[] interfaceNames) throws ClassNotFoundException {
Class[] interfaces = AopUtils.toInterfaceArray(interfaceNames);
setInterfaces(interfaces);
}
2):advisor类的名字,从这个我们可以知道代理规则; public void setInterceptorNames(String[] interceptorNames) {
this.interceptorNames = interceptorNames;
}
3):代理类的名字;
public void setTargetName(String targetName) {
this.targetName = targetName;
}
然后我们来分析一下getObject()方法:
public Object getObject() throws BeansException {
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();
}
}
从这个方法,我们可见,ProxyBeanFactory根据上述信息给我们构造了一个PrototypeInstance();
private synchronized Object newPrototypeInstance() {
// In the case of a prototype, we need to give the proxy
// an independent instance of the configuration.
// In this case, no proxy will have an instance of this object's configuration,
// but will have an independent copy.
if (logger.isDebugEnabled()) {
logger.debug("Creating copy of prototype ProxyFactoryBean config: " + this);
}
AdvisedSupport copy = new AdvisedSupport();
// The copy needs a fresh advisor chain, and a fresh TargetSource.
TargetSource targetSource = freshTargetSource();
copy.copyConfigurationFrom(this, targetSource, freshAdvisorChain());
if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
// Rely on AOP infrastructure to tell us what interfaces to proxy.
copy.setInterfaces(ClassUtils.getAllInterfacesForClass(targetSource.getTargetClass()));
}
copy.setFrozen(this.freezeProxy);
if (logger.isDebugEnabled()) {
logger.debug("Copy has config: " + copy);
}
return getProxy(copy.createAopProxy());
}
构造proxy对象是有ProxySupport类完成的,他把这个对象委托给了一个AopProxyFactory工厂,而这个理之所有要委托给一个工厂,是因为,生成这个代理类是有选择的:
public AopProxy createAopProxy(AdvisedSupport advisedSupport) throws AopConfigException {
if (advisedSupport.isOptimize() || advisedSupport.isProxyTargetClass() ||
advisedSupport.getProxiedInterfaces().length == 0) {
if (!cglibAvailable) {
throw new AopConfigException(
"Cannot proxy target class because CGLIB2 is not available. " +
"Add CGLIB to the class path or specify proxy interfaces.");
}
return CglibProxyFactory.createCglibProxy(advisedSupport);
}
else {
return new JdkDynamicAopProxy(advisedSupport);
}
}
这里生成动态代理类有两种方式,一种是如果用户没有给被代理类实现接口,那么,就会使用cglib来生成代理类,如果制定了实现接口,那么就会使用jdk的InvocationHandler接口实现代理;
这个AopProxy类是一个Proxy Object的包装类;
public interface AopProxy {
/**
* Create a new proxy object.
* <p>Uses the most optimal default class loader (if necessary for proxy creation):
* usually, the thread context class loader.
* @see java.lang.Thread#getContextClassLoader()
*/
Object getProxy();
/**
* Create a new proxy object.
* <p>Uses the given class loader (if necessary for proxy creation).
* <code>null</code> will simply be passed down and thus lead to the low-level
* proxy facility's default, which is usually different from the default chosen
* by the AopProxy implementation's <code>getProxy</code> method.
* @param classLoader the class loader to create the proxy with
* (or <code>null</code> for the low-level proxy facility's default)
*/
Object getProxy(ClassLoader classLoader);
}
能够从中得到代理的Object;
相关文章推荐
- 做一个合格的程序猿之浅析Spring AOP源码(十四) 分析ProxyFactoryBean
- Spring源码分析之ProxyFactoryBean方式实现Aop功能的分析
- 浅析Spring AOP源码(十四) 分析ProxyFactoryBean
- Spring源代码分析(4)---BeanFactoryPostProcessor(看见的不一定是真的)
- Spring AOP之ProxyFactoryBean与BeanNameAutoProxyCreator
- Spring -- org.springframework.aop.framework.ProxyFactoryBean
- spring 直接使用ProxyFactoryBean 实现AOP 流程小结
- spring aop(五)--ProxyFactoryBean创建代理的实现
- Spring源代码分析(17)---JndiObjectFactoryBean分析(小样,花名册上有你)
- Spring ProxyFactoryBean 是如何实现所有的AOP proxy都有可能转为Advised接口的?
- ProxyFactoryBean 实现 Aop 功能源码分析
- Spring基础-AOP之ProxyFactoryBean及相关内容(五)
- Spring源码-AOP(五)-ProxyFactoryBean
- Spring的AOP实现方式—ProxyFactoryBean配置方式实现源码剖析
- Spring源码阅读-使用ProxyFactoryBean实现AOP
- Spring AOP实现机制(二)--ProxyFactoryBean---将Spring AOP和Spring IoC容器相结合
- Spring Aop(十三)——ProxyFactoryBean创建代理对象
- Spring AOP小测试(ProxyFactoryBean)
- Spring源码学习-5.ProxyFactoryBean实现与源代码分析
- Spring学习笔记 —— AOP(面向切面编程) 之使用ProxyFactoryBean实现AOP