Spring读源码系列之AOP--04---proxyFactory创建代理对象
- 引言
- ProxyCreatorSupport---代理对象创建支持
- AopProxyFactory---生产AopProxy的工厂
- DefaultAopProxyFactory---选择是使用cglib还是jdk动态代理来创建代理对象
- ProxyFactoryBean----与IOC结合使用来创建代理类
- ProxyFactoryBean使用演示
- ProxyFactoryBean脱离IoC容器使用
- ProxyFactory---编码创建aop代理,可脱离IOC使用
- ProxyFactory使用演示
- AspectJProxyFactory----处理标注了@AspectJ的切面
- 使用演示
- 注意
- 总结
引言
Spring作为一个优秀的框架,提供了多种应用层面上代理的方式:ProxyFactoryBean、ProxyFactory、AspectJProxyFactory
注意:此处这里指的是Spring提供的应用层得方式,并不是指的底层实现方式。底层实现方式现在只有业界都熟悉的两种:JDK动态代理和CGLIB代理~
ProxyFactoryBean是将我们的AOP和IOC融合起来,而ProxyFactory 则是只能通过代码硬编码进行编写 一般都是给spring自己使用。而AspectJ是目前大家最常用的集成AspectJ和Spring~~~
Spring AOP进化史:
阅读本文前,请先弄清楚aop底层各个组件的作用和之间的关系,具体参考下文:
Spring读源码系列之AOP–03—aop底层基础类学习
ProxyCreatorSupport—代理对象创建支持
代理工厂的基类。提供对可配置 AopProxyFactory 的便捷访问。
代码语言:javascript复制public class ProxyCreatorSupport extends AdvisedSupport {
//负责生产代理对象的工厂
private AopProxyFactory aopProxyFactory;
//监听器
private final List<AdvisedSupportListener> listeners = new ArrayList<>();
/** Set to true when the first AOP proxy has been created. */
private boolean active = false;
public ProxyCreatorSupport() {
this.aopProxyFactory = new DefaultAopProxyFactory();
}
public ProxyCreatorSupport(AopProxyFactory aopProxyFactory) {
Assert.notNull(aopProxyFactory, "AopProxyFactory must not be null");
this.aopProxyFactory = aopProxyFactory;
}
public void setAopProxyFactory(AopProxyFactory aopProxyFactory) {
Assert.notNull(aopProxyFactory, "AopProxyFactory must not be null");
this.aopProxyFactory = aopProxyFactory;
}
public AopProxyFactory getAopProxyFactory() {
return this.aopProxyFactory;
}
public void addListener(AdvisedSupportListener listener) {
Assert.notNull(listener, "AdvisedSupportListener must not be null");
this.listeners.add(listener);
}
public void removeListener(AdvisedSupportListener listener) {
Assert.notNull(listener, "AdvisedSupportListener must not be null");
this.listeners.remove(listener);
}
/**
子类应该调用它来获得一个新的 AOP 代理。他们不应该以 this 作为参数来创建 AOP 代理。
*/
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
/**
* Activate this proxy configuration.
* @see AdvisedSupportListener#activated
*/
private void activate() {
this.active = true;
for (AdvisedSupportListener listener : this.listeners) {
listener.activated(this);
}
}
/**
* Propagate advice change event to all AdvisedSupportListeners.
* @see AdvisedSupportListener#adviceChanged
*/
@Override
protected void adviceChanged() {
super.adviceChanged();
synchronized (this) {
if (this.active) {
for (AdvisedSupportListener listener : this.listeners) {
listener.adviceChanged(this);
}
}
}
}
/**
* Subclasses can call this to check whether any AOP proxies have been created yet.
*/
protected final synchronized boolean isActive() {
return this.active;
}
}
主要就是通过createAopProxy方法来创建一个代理对象
AopProxyFactory—生产AopProxy的工厂
由能够基于 AdvisedSupport 配置对象创建 AOP 代理的工厂实现的接口。
Proxies 应该遵守下面的约定:
- 他们应该实现配置指示应该被代理的所有接口。
- 他们应该实现 Advised 接口.
- 他们应该实现 equals 方法来比较代理接口、advice和目标对象。
- 如果所有advisors和目标对象都是可序列化的,它们应该是可序列化的。
- 如果advisors和目标是线程安全的,它们应该是线程安全的。
代理可能允许也可能不允许更改advice。如果它们不允许更改advice(例如,因为配置被冻结),代理应该在尝试更改建议时抛出 AopConfigException。
代码语言:javascript复制public interface AopProxyFactory {
/**
* Create an AopProxy for the given AOP configuration.
*/
AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException;
}
DefaultAopProxyFactory—选择是使用cglib还是jdk动态代理来创建代理对象
默认 AopProxyFactory 实现,创建 CGLIB 代理或 JDK 动态代理。
如果给定的 AdvisedSupport 实例满足以下条件之一,则创建 CGLIB 代理:
- the optimize flag is
- the proxyTargetClass flag is set
- no proxy interfaces have been specified
通常,指定 proxyTargetClass 以强制执行 CGLIB 代理,或指定一个或多个接口以使用 JDK 动态代理。
代码语言:javascript复制public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!NativeDetector.inNativeImage() &&
//满足下面三个条件其中一个,则采用cglib代理
(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 {
//采用jdk动态代理
return new JdkDynamicAopProxy(config);
}
}
private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
//通过AdvisedSupport拿到当前代理对象需要实现的接口,如果没有需要实现的接口或者需要实现的接口只有一个并且这个接口继承至 SpringProxy
//返回true
Class<?>[] ifcs = config.getProxiedInterfaces();
return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
}
}
ProxyFactoryBean----与IOC结合使用来创建代理类
FactoryBean 实现,它基于 Spring BeanFactory 中的 bean 构建 AOP 代理。
FactoryBean是spring中提供通过bean工厂的方式来向spring中注入bean,一般用于复杂bean的构建
ProxyFactoryBean维护了一个interceptorNames数组,该数组存放了所有应用于当前代理对象的拦截器,在旧版spring实现的,该数组最后一个元素是目标 bean 的名称或 TargetSource;但是,通常最好改用“targetName”“target”“targetSource”属性。
因为我们知道拦截器链中的拦截器全部调用完成后,会去调用目标方法,因此在spring中是将拦截器名称数组最后一个设置为了目标对象
返回的代理对象都可以转换为Advised,我们还可以脱离IOC单独使用ProxyFactory,通过编码方式来构建。
代码语言:javascript复制public class ProxyFactoryBean extends ProxyCreatorSupport
implements FactoryBean<Object>, BeanClassLoaderAware, BeanFactoryAware {
/**
* This suffix in a value in an interceptor list indicates to expand globals.
* 如果拦截器名称以*结尾,说明是全局拦截器,需要去当前IOC和父容器中搜索获得
*/
public static final String GLOBAL_SUFFIX = "*";
protected final Log logger = LogFactory.getLog(getClass());
//存放应用到当前代理对象的拦截器名称数组
@Nullable
private String[] interceptorNames;
//目标对象名称
@Nullable
private String targetName;
//自动探测接口,默认开启--即可以自行选择使用jdk还是cglib动态代理
private boolean autodetectInterfaces = true;
//生成的代理对象是单例的还是多例的
private boolean singleton = true;
//获取全局共享的AdvisorAdapterRegistry,负责进行相关适配工作
private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance();
//是否冻结代理对象的相关配置
private boolean freezeProxy = false;
//加载代理对象的加载器
@Nullable
private transient ClassLoader proxyClassLoader = ClassUtils.getDefaultClassLoader();
//加载器是否被手动配置了
private transient boolean classLoaderConfigured = false;
//拿到IOC容器
@Nullable
private transient BeanFactory beanFactory;
//拦截器链是否完成了初始化
private boolean advisorChainInitialized = false;
//如果生成的代理对象是单例的,那么该属性就用来缓存该生产的代理类单例对象
@Nullable
private Object singletonInstance;
/**
手动指定代理类需要实现的接口,如果没指定,则使用cglib进行代理
但是因为默认开启了自动接口探测功能,所以这里一般不需要手动指定
*/
public void setProxyInterfaces(Class<?>[] proxyInterfaces) throws ClassNotFoundException {
//设置到父类AdvisedSupport的interfaces接口集合中
setInterfaces(proxyInterfaces);
}
/**
设置当前代理对象关联的一组拦截器名称数组
*/
public void setInterceptorNames(String... interceptorNames) {
this.interceptorNames = interceptorNames;
}
/**
目标对象名字
*/
public void setTargetName(String targetName) {
this.targetName = targetName;
}
/**
对自动探测功能进行设置
*/
public void setAutodetectInterfaces(boolean autodetectInterfaces) {
this.autodetectInterfaces = autodetectInterfaces;
}
/**
* Set the value of the singleton property. Governs whether this factory
* should always return the same proxy instance (which implies the same target)
* or whether it should return a new prototype instance, which implies that
* the target and interceptors may be new instances also, if they are obtained
* from prototype bean definitions. This allows for fine control of
* independence/uniqueness in the object graph.
* 设置当前FactoryBean生产的代理对象是单例的还是多例的
*/
public void setSingleton(boolean singleton) {
this.singleton = singleton;
}
public void setAdvisorAdapterRegistry(AdvisorAdapterRegistry advisorAdapterRegistry) {
this.advisorAdapterRegistry = advisorAdapterRegistry;
}
@Override
public void setFrozen(boolean frozen) {
this.freezeProxy = frozen;
}
public void setProxyClassLoader(@Nullable ClassLoader classLoader) {
this.proxyClassLoader = classLoader;
this.classLoaderConfigured = (classLoader != null);
}
//默认proxyClassLoader 是BeanClassLoader
//该方法因为继承了BeanClassLoaderAware
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
if (!this.classLoaderConfigured) {
this.proxyClassLoader = classLoader;
}
}
//该方法继承至BeanFactoryAware
@Override
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
checkInterceptorNames();
}
/**
该方法继承至FactoryBean
*/
@Override
@Nullable
public Object getObject() throws BeansException {
//初始化拦截器链
initializeAdvisorChain();
//判断是单例还是多例,分别处理
if (isSingleton()) {
//单例
return getSingletonInstance();
}
else {
if (this.targetName == null) {
logger.info("Using non-singleton proxies with singleton targets is often undesirable. "
"Enable prototype proxies by setting the 'targetName' property.");
}
//多例
return newPrototypeInstance();
}
}
/**
继承FactoryBean的方法,返回创建对象的类型。将检查单例实例是否已创建,否则回退到代理接口(如果只有一个)、目标 bean 类型或 TargetSource 的目标类。
*/
@Override
public Class<?> getObjectType() {
synchronized (this) {
//singletonInstance 缓存已经创建过的单例代理对象---单例在当前工厂内部会进行缓存,通过singletonInstance完成
if (this.singletonInstance != null) {
return this.singletonInstance.getClass();
}
}
//如果代理对象需要实现的接口只有一个,那么返回的代理对象类型就为这个接口
Class<?>[] ifcs = getProxiedInterfaces();
if (ifcs.length == 1) {
return ifcs[0];
}
//如果需要实现的接口大于一个,那么会创建一个代理类实现这些接口,返回这个代理类的类型作为代理对象的类型
else if (ifcs.length > 1) {
return createCompositeInterface(ifcs);
}
//尝试从IOC中获取bean的类型
else if (this.targetName != null && this.beanFactory != null) {
return this.beanFactory.getType(this.targetName);
}
else {
//返回目标对象的类型
return getTargetClass();
}
}
//继承至FctoryBean的方法,表示当前生产的对象是否是单例的
@Override
public boolean isSingleton() {
return this.singleton;
}
/**
* Create a composite interface Class for the given interfaces,
* implementing the given interfaces in one single Class.
* The default implementation builds a JDK proxy class for the
* given interfaces.
*/
protected Class<?> createCompositeInterface(Class<?>[] interfaces) {
//通过jdk动态代理创建一个代理类继承传入的接口,然后返回代理类类型
return ClassUtils.createCompositeInterface(interfaces, this.proxyClassLoader);
}
/**
* Return the singleton instance of this class's proxy object,
* lazily creating it if it hasn't been created already.
* 获取类型为单例的代理对象
*/
private synchronized Object getSingletonInstance() {
//singletonInstance不为空,说明单例对象已经创建过并且被缓存起来了
if (this.singletonInstance == null) {
//父类AdvisedSupport中维护了一个targetSource 属性---targetSource负责包装目标对象
//从容器中找到targetName对应的bean,然后包装为TargetSource后返回
this.targetSource = freshTargetSource();
//开启了接口自动探测并且当前类没有实现任何接口并且没有设置ProxyTargetClass为true
if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
// Rely on AOP infrastructure to tell us what interfaces to proxy.
//获取目标类的class
Class<?> targetClass = getTargetClass();
if (targetClass == null) {
throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
}
//getAllInterfacesForClass这里会返回当前类继承和父类实现的所有接口
//这里已经确定了当前类没有实现任何接口--那么这里判断的是当前targetClass为一个接口的时候
//会将目标类实现的接口放入父类advisedSupport的interfaces集合中,代表代理类需要实现的接口
//这里setInterfaces会将探测到的接口放入父类AdvisedSupport的interfaces接口集合中
//然后最后选择cglib还是jdk动态代理是需要对这个interfaces是否存在元素进行判断
setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
}
// Initialize the shared singleton instance.
//锁住代理类的相关配置,不让其被修改
super.setFrozen(this.freezeProxy);
//获取代理对象---createAopProxy()通过DefaultAopProxyFactory创建代理对象--返回的是AopProxy
//getProxy()获取到AopProxy包裹的代理对象
this.singletonInstance = getProxy(createAopProxy());
}
return this.singletonInstance;
}
/**
代理对象是多例:除了每次创建的代理对象都单独创建一个配置实例外并且没有singletonInstance 缓存外,其余和单例一致
*/
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.
//在这种情况下,没有代理将拥有此对象配置的实例,但会有独立的副本。
//即每次获取的代理对象都分配一个新的配置实例
ProxyCreatorSupport copy = new ProxyCreatorSupport(getAopProxyFactory());
// The copy needs a fresh advisor chain, and a fresh TargetSource.
TargetSource targetSource = freshTargetSource();
// freshAdvisorChain()刷新AdvisorChain主要是将PrototypePlaceholderAdvisor中的PrototypeAdvisorName获取到
//并且从容器中取得对应的实例,然后加上一些共享的Advisor一起放入集合并返回
copy.copyConfigurationFrom(this, targetSource, freshAdvisorChain());
if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
// Rely on AOP infrastructure to tell us what interfaces to proxy.
Class<?> targetClass = targetSource.getTargetClass();
if (targetClass != null) {
copy.setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
}
}
copy.setFrozen(this.freezeProxy);
return getProxy(copy.createAopProxy());
}
/**
* Return the proxy object to expose.
* 获取aopProxy内部包裹的代理对象实例
*/
protected Object getProxy(AopProxy aopProxy) {
return aopProxy.getProxy(this.proxyClassLoader);
}
/**
* Check the interceptorNames list whether it contains a target name as final element.
* If found, remove the final name from the list and set it as targetName
*/
private void checkInterceptorNames() {
//设置了拦截器数组才进行检查
if (!ObjectUtils.isEmpty(this.interceptorNames)) {
//拿到数组最后一个元素
String finalName = this.interceptorNames[this.interceptorNames.length - 1];
//如果targetName没有设置,并且targetSource 是空的
if (this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
// The last name in the chain may be an Advisor/Advice or a target/TargetSource.
// Unfortunately we don't know; we must look at type of the bean.
//那么拦截器数组最后一个元素不是全局拦截器并且也不是Advisor和Advice的情况下
if (!finalName.endsWith(GLOBAL_SUFFIX) && !isNamedBeanAnAdvisorOrAdvice(finalName)) {
// The target isn't an interceptor.
//那么就是我们需要的targetBean的BeanName了
this.targetName = finalName;
if (logger.isDebugEnabled()) {
logger.debug("Bean with name '" finalName "' concluding interceptor chain "
"is not an advisor class: treating it as a target or TargetSource");
}
//最后一个元素去掉
this.interceptorNames = Arrays.copyOf(this.interceptorNames, this.interceptorNames.length - 1);
}
}
}
}
/**
* Look at bean factory metadata to work out whether this bean name,
* which concludes the interceptorNames list, is an Advisor or Advice,
* or may be a target.
*/
private boolean isNamedBeanAnAdvisorOrAdvice(String beanName) {
Assert.state(this.beanFactory != null, "No BeanFactory set");
Class<?> namedBeanClass = this.beanFactory.getType(beanName);
if (namedBeanClass != null) {
return (Advisor.class.isAssignableFrom(namedBeanClass) || Advice.class.isAssignableFrom(namedBeanClass));
}
// Treat it as an target bean if we can't tell.
if (logger.isDebugEnabled()) {
logger.debug("Could not determine type of bean with name '" beanName
"' - assuming it is neither an Advisor nor an Advice");
}
return false;
}
/**
创建advisors(拦截器)链。
每次添加新的原型实例时,
都会刷新来自 BeanFactory 的advisors。
通过工厂 API 以编程方式添加的拦截器不受此类更改的影响。
*/
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
//如果已经初始化过了,就返回
if (this.advisorChainInitialized) {
return;
}
//interceptorNames数组不为空的情况下beanFactory容器必须要设置一个与其进行关联,
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...
//处理Globals advisor
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 (name.endsWith(GLOBAL_SUFFIX)) {
if (!(this.beanFactory instanceof ListableBeanFactory)) {
throw new AopConfigException(
"Can only use global advisors or interceptors with a ListableBeanFactory");
}
//添加全局advisor
addGlobalAdvisors((ListableBeanFactory) this.beanFactory,
name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
}
//不是全局的advisor
else {
// If we get here, we need to add a named interceptor.
// We must check if it's a singleton or prototype.
Object advice;
//如果是advice单例的,那么调用getBean完成创建和初始化
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.
//在拦截器链中使用,我们需要在创建代理时用原型替换 bean。
advice = new PrototypePlaceholderAdvisor(name);
}
//添加进父类advisedSupport的advisors集合
addAdvisorOnChainCreation(advice);
}
}
}
this.advisorChainInitialized = true;
}
/**
newPrototypeInstance方法中会调用该方法---为的是给代理类每次返回不同的Advisors and Advice
* Return an independent advisor chain.
* We need to do this every time a new prototype instance is returned,
* to return distinct instances of prototype Advisors and Advices.
*/
private List<Advisor> freshAdvisorChain() {
Advisor[] advisors = getAdvisors();
List<Advisor> freshAdvisors = new ArrayList<>(advisors.length);
for (Advisor advisor : advisors) {
//要求对应的advisor必须也是多例的
if (advisor instanceof PrototypePlaceholderAdvisor) {
PrototypePlaceholderAdvisor pa = (PrototypePlaceholderAdvisor) advisor;
if (logger.isDebugEnabled()) {
logger.debug("Refreshing bean named '" pa.getBeanName() "'");
}
// Replace the placeholder with a fresh prototype instance resulting from a getBean lookup
if (this.beanFactory == null) {
throw new IllegalStateException("No BeanFactory available anymore (probably due to "
"serialization) - cannot resolve prototype advisor '" pa.getBeanName() "'");
}
Object bean = this.beanFactory.getBean(pa.getBeanName());
//bean转换为Advisor---通过适配器
Advisor refreshedAdvisor = namedBeanToAdvisor(bean);
freshAdvisors.add(refreshedAdvisor);
}
else {
// Add the shared instance.
freshAdvisors.add(advisor);
}
}
//对于多例的代理对象来说,每一次返回的advisors集合也是不同的
//并且只会返回同样是多例的advisors
return freshAdvisors;
}
/**
* Add all global interceptors and pointcuts.
*/
private void addGlobalAdvisors(ListableBeanFactory beanFactory, String prefix) {
String[] globalAdvisorNames =
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, Advisor.class);
String[] globalInterceptorNames =
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, Interceptor.class);
if (globalAdvisorNames.length > 0 || globalInterceptorNames.length > 0) {
List<Object> beans = new ArrayList<>(globalAdvisorNames.length globalInterceptorNames.length);
for (String name : globalAdvisorNames) {
if (name.startsWith(prefix)) {
beans.add(beanFactory.getBean(name));
}
}
for (String name : globalInterceptorNames) {
if (name.startsWith(prefix)) {
beans.add(beanFactory.getBean(name));
}
}
AnnotationAwareOrderComparator.sort(beans);
for (Object bean : beans) {
addAdvisorOnChainCreation(bean);
}
}
}
/**
* Invoked when advice chain is created.
* <p>Add the given advice, advisor or object to the interceptor list.
* Because of these three possibilities, we can't type the signature
* more strongly.
* @param next advice, advisor or target object
*/
private void addAdvisorOnChainCreation(Object next) {
// We need to convert to an Advisor if necessary so that our source reference
// matches what we find from superclass interceptors.
addAdvisor(namedBeanToAdvisor(next));
}
/**
* Return a TargetSource to use when creating a proxy. If the target was not
* specified at the end of the interceptorNames list, the TargetSource will be
* this class's TargetSource member. Otherwise, we get the target bean and wrap
* it in a TargetSource if necessary.
*/
private TargetSource freshTargetSource() {
if (this.targetName == null) {
// Not refreshing target: bean name not specified in 'interceptorNames'
return this.targetSource;
}
else {
if (this.beanFactory == null) {
throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) "
"- cannot resolve target with name '" this.targetName "'");
}
if (logger.isDebugEnabled()) {
logger.debug("Refreshing target with name '" this.targetName "'");
}
Object target = this.beanFactory.getBean(this.targetName);
return (target instanceof TargetSource ? (TargetSource) target : new SingletonTargetSource(target));
}
}
/**
* Convert the following object sourced from calling getBean() on a name in the
* interceptorNames array to an Advisor or TargetSource.
*/
private Advisor namedBeanToAdvisor(Object next) {
try {
return this.advisorAdapterRegistry.wrap(next);
}
catch (UnknownAdviceTypeException ex) {
// We expected this to be an Advisor or Advice,
// but it wasn't. This is a configuration error.
throw new AopConfigException("Unknown advisor type " next.getClass()
"; can only include Advisor or Advice type beans in interceptorNames chain "
"except for last entry which may also be target instance or TargetSource", ex);
}
}
/**
* Blow away and recache singleton on an advice change.
*/
@Override
protected void adviceChanged() {
super.adviceChanged();
if (this.singleton) {
logger.debug("Advice has changed; re-caching singleton instance");
synchronized (this) {
this.singletonInstance = null;
}
}
}
//---------------------------------------------------------------------
// Serialization support
//---------------------------------------------------------------------
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
// Rely on default serialization; just initialize state after deserialization.
ois.defaultReadObject();
// Initialize transient fields.
this.proxyClassLoader = ClassUtils.getDefaultClassLoader();
}
/**
* Used in the interceptor chain where we need to replace a bean with a prototype
* on creating a proxy.
*/
private static class PrototypePlaceholderAdvisor implements Advisor, Serializable {
private final String beanName;
private final String message;
public PrototypePlaceholderAdvisor(String beanName) {
this.beanName = beanName;
this.message = "Placeholder for prototype Advisor/Advice with bean name '" beanName "'";
}
public String getBeanName() {
return this.beanName;
}
@Override
public Advice getAdvice() {
throw new UnsupportedOperationException("Cannot invoke methods: " this.message);
}
@Override
public boolean isPerInstance() {
throw new UnsupportedOperationException("Cannot invoke methods: " this.message);
}
@Override
public String toString() {
return this.message;
}
}
}
该类的核心思路如下:
ProxyFactoryBean的很多方法只不过都是负责解析实例化的任务,然后把这些实例化或者解析好的属性加入父类即AdvisedSupport的相关配置属性中去,然后当需要创建代理对象的时候,依赖ProxyCreatorSupport提供的方法完成,并且会传入自身实例,其实是为了从父类AdvisedSupport获取相关配置信息,来完成代理对象的最终创建
该类并没有实现自动探测容器内部拦截器bean的功能,那个探测全局拦截器的功能相当于一个模糊搜索,将满足条件的拦截器都加入到父类advisedSupport集合中
ProxyFactoryBean使用演示
代码语言:javascript复制// 先定义一个前置通知
@Component("logMethodBeforeAdvice")
public class LogMethodBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("this is LogMethodBeforeAdvice");
}
}
// 注册一个代理Bean
@Bean
public ProxyFactoryBean proxyFactoryBean(HelloService helloService) {
ProxyFactoryBean factoryBean = new ProxyFactoryBean();
//代理的目标对象 效果同setTargetSource(@Nullable TargetSource targetSource)
// 此处需要注意的是,这里如果直接new,那么该类就不能使用@Autowired之类的注入 因此建议此处还是从容器中去拿
// 因此可以写在入参上(这也是标准的写法~~)
//factoryBean.setTarget(new HelloServiceImpl());
factoryBean.setTarget(helloService);
// setInterfaces和setProxyInterfaces的效果是相同的。设置需要被代理的接口,
// 若没有实现接口,那就会采用cglib去代理
// 需要说明的一点是:这里不设置也能正常被代理(若你没指定,Spring内部会去帮你找到所有的接口,然后全部代理上~~~~~~~~~~~~) 设置的好处是只代理指定的接口
factoryBean.setInterfaces(HelloService.class);
//factoryBean.setProxyInterfaces(new Class[]{HelloService.class});
// 需要植入进目标对象的bean列表 此处需要注意:这些bean必须实现类 org.aopalliance.intercept.MethodInterceptor或 org.springframework.aop.Advisor的bean ,配置中的顺序对应调用的顺序
factoryBean.setInterceptorNames("logMethodBeforeAdvice");
// 若设置为true,强制使用cglib,默认是false的
//factoryBean.setProxyTargetClass(true);
return factoryBean;
}
// main方法测试:
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(RootConfig.class);
//expected single matching bean but found 2: helloServiceImpl,proxyFactoryBean
// 如果通过类型获取,会找到两个Bean:一个我们自己的实现类、一个ProxyFactoryBean所生产的代理类 而此处我们显然是希望要生成的代理类的 因此我们只能通过名称来(或者加上@Primary)
//HelloService bean = applicationContext.getBean(HelloService.class);
HelloService bean = (HelloService) applicationContext.getBean("proxyFactoryBean");
bean.hello();
System.out.println(bean); //com.fsx.service.HelloServiceImpl@4e50c791
System.out.println(bean.getClass()); //class com.sun.proxy.$Proxy22 用得JDK的动态代理
// 顺便说一句:这样也是没错得。因为Spring AOP代理出来的每个代理对象,都默认实现了这个接口(它是个标记接口)
// 它这个也就类似于所有的JDK代理出来的,都是Proxy的子类是一样的思想~
SpringProxy springProxy = (SpringProxy) bean;
}
输出:
this is LogMethodBeforeAdvice
this is my method~~
ProxyFactoryBean脱离IoC容器使用
虽然它大多数都是结合IoC容器一起使用,但是它脱离容器依然是可议单独使用的(毕竟生成代理得核心功能在父类ProxyCreatorSupport上,和容器无关的)。比如如下:
代码语言:javascript复制public class Main {
public static void main(String[] args) {
String pointcutExpression = "execution( int com.fsx.maintest.Person.run() )";
// =============================================================
//因为我们要使用AspectJ,所以此处采用AspectJProxyFactory,当然你也可以使用和容器相关的ProxyFactoryBean
ProxyFactoryBean factory = new ProxyFactoryBean();
factory.setTarget(new Person());
//AspectJProxyFactory factory = new AspectJProxyFactory(new Person());
//声明一个aspectj切点,一张切面
AspectJExpressionPointcut cut = new AspectJExpressionPointcut();
cut.setExpression(pointcutExpression); // 设置切点表达式
// 声明一个通知(此处使用环绕通知 MethodInterceptor )
Advice advice = (MethodInterceptor) invocation -> {
System.out.println("============>放行前拦截...");
Object obj = invocation.proceed();
System.out.println("============>放行后拦截...");
return obj;
};
//切面=切点 通知
// 它还有个构造函数:DefaultPointcutAdvisor(Advice advice); 用的切面就是Pointcut.TRUE,所以如果你要指定切面,请使用自己指定的构造函数
// Pointcut.TRUE:表示啥都返回true,也就是说这个切面作用于所有的方法上/所有的方法
// addAdvice();方法最终内部都是被包装成一个 `DefaultPointcutAdvisor`,且使用的是Pointcut.TRUE切面,因此需要注意这些区别
Advisor advisor = new DefaultPointcutAdvisor(cut, advice);
factory.addAdvisor(advisor);
//Person p = factory.getProxy();
Person p = (Person) factory.getObject();
// 执行方法
p.run();
p.run(10);
p.say();
p.sayHi("Jack");
p.say("Tom", 666);
}
}
class Person {
public int run() {
System.out.println("我在run...");
return 0;
}
public void run(int i) {
System.out.println("我在run...<" i ">");
}
public void say() {
System.out.println("我在say...");
}
public void sayHi(String name) {
System.out.println("Hi," name ",你好");
}
public int say(String name, int i) {
System.out.println(name "----" i);
return 0;
}
}
输出:
代码语言:javascript复制============>放行前拦截...
我在run...
============>放行后拦截...
我在run...<10>
我在say...
Hi,Jack,你好
Tom----666
ProxyFactory—编码创建aop代理,可脱离IOC使用
用于编程使用的 AOP 代理工厂,而不是通过 bean 工厂中的声明性设置。
此类提供了一种在自定义用户代码中获取和配置 AOP 代理实例的简单方法。
它和Spring容器没啥关系,可议直接创建代理来使用:
代码语言:javascript复制public class ProxyFactory extends ProxyCreatorSupport {
public ProxyFactory() {
}
//设置目标对象加自动探测目标对象实现的接口
public ProxyFactory(Object target) {
setTarget(target);
setInterfaces(ClassUtils.getAllInterfaces(target));
}
/**
不指定目标对象,只会指定需要代理的接口,但是必须添加拦截器
*/
public ProxyFactory(Class<?>... proxyInterfaces) {
setInterfaces(proxyInterfaces);
}
/**
* Create a new ProxyFactory for the given interface and interceptor.
* Convenience method for creating a proxy for a single interceptor,
* assuming that the interceptor handles all calls itself rather than
* delegating to a target, like in the case of remoting proxies.
*/
public ProxyFactory(Class<?> proxyInterface, Interceptor interceptor) {
addInterface(proxyInterface);
addAdvice(interceptor);
}
/**
* Create a ProxyFactory for the specified TargetSource,
* making the proxy implement the specified interface.
* @param proxyInterface the interface that the proxy should implement
* @param targetSource the TargetSource that the proxy should invoke
*/
public ProxyFactory(Class<?> proxyInterface, TargetSource targetSource) {
addInterface(proxyInterface);
setTargetSource(targetSource);
}
/**
* Create a new proxy according to the settings in this factory.
* <p>Can be called repeatedly. Effect will vary if we've added
* or removed interfaces. Can add and remove interceptors.
* <p>Uses a default class loader: Usually, the thread context class loader
* (if necessary for proxy creation).
* @return the proxy object
*/
public Object getProxy() {
//调用父类AdvisedSupport的createAopProxy()方法创建一个AopProxy对象
//通过调用AopProx对象的getProxy方法,拿到代理对象
return createAopProxy().getProxy();
}
/**
* Create a new proxy according to the settings in this factory.
* Can be called repeatedly. Effect will vary if we've added
* or removed interfaces. Can add and remove interceptors.
* Uses the given class loader (if necessary for proxy creation).
*/
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
/**
* Create a new proxy for the given interface and interceptor.
* <p>Convenience method for creating a proxy for a single interceptor,
* assuming that the interceptor handles all calls itself rather than
* delegating to a target, like in the case of remoting proxies.
* @param proxyInterface the interface that the proxy should implement
* @param interceptor the interceptor that the proxy should invoke
* @return the proxy object
* @see #ProxyFactory(Class, org.aopalliance.intercept.Interceptor)
*/
@SuppressWarnings("unchecked")
public static <T> T getProxy(Class<T> proxyInterface, Interceptor interceptor) {
return (T) new ProxyFactory(proxyInterface, interceptor).getProxy();
}
/**
* Create a proxy for the specified {@code TargetSource},
* implementing the specified interface.
* @param proxyInterface the interface that the proxy should implement
* @param targetSource the TargetSource that the proxy should invoke
* @return the proxy object
* @see #ProxyFactory(Class, org.springframework.aop.TargetSource)
*/
@SuppressWarnings("unchecked")
public static <T> T getProxy(Class<T> proxyInterface, TargetSource targetSource) {
return (T) new ProxyFactory(proxyInterface, targetSource).getProxy();
}
/**
* Create a proxy for the specified {@code TargetSource} that extends
* the target class of the {@code TargetSource}.
* @param targetSource the TargetSource that the proxy should invoke
* @return the proxy object
*/
public static Object getProxy(TargetSource targetSource) {
if (targetSource.getTargetClass() == null) {
throw new IllegalArgumentException("Cannot create class proxy for TargetSource with null target class");
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTargetSource(targetSource);
//采用cglib代理
proxyFactory.setProxyTargetClass(true);
return proxyFactory.getProxy();
}
}
该类提供了一个更加便捷的方法来创建代理对象,并且不需要依赖IOC
ProxyFactory使用演示
代码语言:javascript复制 public static void main(String[] args) {
ProxyFactory proxyFactory = new ProxyFactory(new HelloServiceImpl());
// 添加两个Advise,一个匿名内部类表示
proxyFactory.addAdvice((AfterReturningAdvice) (returnValue, method, args1, target) ->
System.out.println("AfterReturningAdvice method=" method.getName()));
proxyFactory.addAdvice(new LogMethodBeforeAdvice());
HelloService proxy = (HelloService) proxyFactory.getProxy();
proxy.hello();
}
输出:
this is LogMethodBeforeAdvice
this is my method~~
AfterReturningAdvice method=hello
ProxyFactory的原理就是ProxyCreatorSupport#createAopProxy这个方法,其余的没啥了
AspectJProxyFactory----处理标注了@AspectJ的切面
其实ProxyFactory拥有的功能AspectjProxyFactory都有,它可以使用编程的方式去创建代理
在低版本Spring中定义一个切面是比较麻烦的,需要实现特定的接口,并进行一些较为复杂的配置,低版本Spring AOP的配置是被批评最多的地方。Spring听取这方面的批评声音,并下决心彻底改变这一现状。在Spring2.0中,Spring AOP已经焕然一新,你可以使用@AspectJ注解非常容易的定义一个切面,不需要实现任何的接口
AspectJ是目前大家最常用的 起到集成AspectJ和Spring,也就是我们平时长谈的:自动代理模式。它整个代理的过程全部交给Spring内部去完成,无侵入。
我们只需要配置切面、通知、切点表达式就能自动的实现切入的效果,使用起来极其方便,对调用者可以说是非常透明化的。相信这也是为何当下最流行这种方式的原因~
代码语言:javascript复制public class AspectJProxyFactory extends ProxyCreatorSupport {
/**缓存单例的切面实例**/
private static final Map<Class<?>, Object> aspectCache = new ConcurrentHashMap<>();
//将标注了AspectJ注解的切面类解析为一组advisors集合--下面会分析该工厂的继承体系
private final AspectJAdvisorFactory aspectFactory = new ReflectiveAspectJAdvisorFactory();
/**
* Create a new AspectJProxyFactory.
*/
public AspectJProxyFactory() {
}
/**
* Create a new AspectJProxyFactory.
* <p>Will proxy all interfaces that the given target implements.
* @param target the target object to be proxied
*/
public AspectJProxyFactory(Object target) {
Assert.notNull(target, "Target object must not be null");
//返回当前类继承的所有接口,作为需要被代理的接口
setInterfaces(ClassUtils.getAllInterfaces(target));
setTarget(target);
}
/**
* Create a new {@code AspectJProxyFactory}.
* No target, only interfaces. Must add interceptors.
*/
public AspectJProxyFactory(Class<?>... interfaces) {
//没有目标对象,只有需要被代理的接口集合
setInterfaces(interfaces);
}
/**
将提供的切面实例添加到链中。
提供的切面实例的类型必须是单例的。
使用此方法时不支持真正的单例生命周期 -
调用者负责管理以这种方式添加的任何切面的生命周期。
*/
public void addAspect(Object aspectInstance) {
Class<?> aspectClass = aspectInstance.getClass();
String aspectName = aspectClass.getName();
//封装切面元数据信息
AspectMetadata am = createAspectMetadata(aspectClass, aspectName);
//only支持单例切面
if (am.getAjType().getPerClause().getKind() != PerClauseKind.SINGLETON) {
throw new IllegalArgumentException(
"Aspect class [" aspectClass.getName() "] does not define a singleton aspect");
}
//从切面工厂获得切面类后,从该切面类中解析出一组advisors加入父类advisedSupport的advisors集合中
addAdvisorsFromAspectInstanceFactory(
//生产切面的工厂,这里工厂的拥有的单例切面实例就是传入的aspectInstance,因此获取时返回的就是这个aspectInstance
new SingletonMetadataAwareAspectInstanceFactory(aspectInstance, aspectName));
}
/**
* Add an aspect of the supplied type to the end of the advice chain.
* @param aspectClass the AspectJ aspect class
*/
public void addAspect(Class<?> aspectClass) {
String aspectName = aspectClass.getName();
AspectMetadata am = createAspectMetadata(aspectClass, aspectName);
//创建切面实例工厂--MetadataAwareAspectInstanceFactory增加一个获取切面元数据的方法
MetadataAwareAspectInstanceFactory instanceFactory = createAspectInstanceFactory(am, aspectClass, aspectName);
//从切面工厂获得切面类后,从该切面类中解析出一组advisors加入父类advisedSupport的advisors集合中
addAdvisorsFromAspectInstanceFactory(instanceFactory);
}
/**
* Add all Advisor Advisors from the supplied MetadataAwareAspectInstanceFactory
* to the current chain. Exposes any special purpose Advisor Advisors if needed.
*/
private void addAdvisorsFromAspectInstanceFactory(MetadataAwareAspectInstanceFactory instanceFactory) {
//AspectJAdvisorFactory可以根据切面工厂,拿到对应的切面类,然后解析得到该切面类中的advisors集合
List<Advisor> advisors = this.aspectFactory.getAdvisors(instanceFactory);
//获取目标对象类型
Class<?> targetClass = getTargetClass();
Assert.state(targetClass != null, "Unresolvable target class");
//找到能够应用到当前目标对象上的advisors
advisors = AopUtils.findAdvisorsThatCanApply(advisors, targetClass);
//是否需要向advisors集合的头部添加一个ExposeInvocationInterceptor
//添加的前提是 advisors集合中包含属于某个AspectJ切面内部的advisor
AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(advisors);
//advisors排序--从实现了ordered接口的重写方法中获取,或者尝试从ordered注解中获取order大小
AnnotationAwareOrderComparator.sort(advisors);
//添加进父类advisedSupport集合中去
addAdvisors(advisors);
}
/**
* Create an {@link AspectMetadata} instance for the supplied aspect type.
* 创建切面元数据信息
*/
private AspectMetadata createAspectMetadata(Class<?> aspectClass, String aspectName) {
AspectMetadata am = new AspectMetadata(aspectClass, aspectName);
if (!am.getAjType().isAspect()) {
throw new IllegalArgumentException("Class [" aspectClass.getName() "] is not a valid aspect type");
}
return am;
}
/**
* Create a {@link MetadataAwareAspectInstanceFactory} for the supplied aspect type. If the aspect type
* has no per clause, then a {@link SingletonMetadataAwareAspectInstanceFactory} is returned, otherwise
* a {@link PrototypeAspectInstanceFactory} is returned.
* 创建切面工厂
*/
private MetadataAwareAspectInstanceFactory createAspectInstanceFactory(
AspectMetadata am, Class<?> aspectClass, String aspectName) {
MetadataAwareAspectInstanceFactory instanceFactory;
//如果当前切面是单例的话---默认都是单例
if (am.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
// Create a shared aspect instance.
//反射创建切面
Object instance = getSingletonAspectInstance(aspectClass);
//SingletonMetadataAwareAspectInstanceFactory负责保管这个创建得到的切面实例
instanceFactory = new SingletonMetadataAwareAspectInstanceFactory(instance, aspectName);
}
else {
// Create a factory for independent aspect instances.
//切面不是单例的,那么就选择一个每次创建新的切面实例的切面工厂
//SimpleMetadataAwareAspectInstanceFactory就是通过反射创建切面,每一次都会反射创建一个新的切面实例
instanceFactory = new SimpleMetadataAwareAspectInstanceFactory(aspectClass, aspectName);
}
return instanceFactory;
}
/**
* Get the singleton aspect instance for the supplied aspect type.
* An instance is created if one cannot be found in the instance cache.
*/
private Object getSingletonAspectInstance(Class<?> aspectClass) {
return aspectCache.computeIfAbsent(aspectClass,
//SimpleAspectInstanceFactory#getAspectInstance就是简单的反射创建切面
clazz -> new SimpleAspectInstanceFactory(clazz).getAspectInstance());
}
/**
* Create a new proxy according to the settings in this factory.
* <p>Can be called repeatedly. Effect will vary if we've added
* or removed interfaces. Can add and remove interceptors.
* <p>Uses a default class loader: Usually, the thread context class loader
* (if necessary for proxy creation).
* @return the new proxy
*/
@SuppressWarnings("unchecked")
public <T> T getProxy() {
//createAopProxy()是父类ProxyCreatorSupport提供的创建代理对象的方法
return (T) createAopProxy().getProxy();
}
/**
* Create a new proxy according to the settings in this factory.
* <p>Can be called repeatedly. Effect will vary if we've added
* or removed interfaces. Can add and remove interceptors.
* <p>Uses the given class loader (if necessary for proxy creation).
* @param classLoader the class loader to create the proxy with
* @return the new proxy
*/
@SuppressWarnings("unchecked")
public <T> T getProxy(ClassLoader classLoader) {
return (T) createAopProxy().getProxy(classLoader);
}
}
使用演示
代码语言:javascript复制@Aspect
class MyAspect {
@Pointcut("execution(* hello(..))")
private void beforeAdd() {
}
@Before("beforeAdd()")
public void before1() {
System.out.println("-----------before-----------");
}
}
在上述切面类定义中我们定义了一个Advisor(采用注解@Aspect标注的),其对应了一个MethodBeforeAdvice,实际上是一个AspectJMethodBeforeAdvice,该Advice对应的是上面的before1()方法,还对应了一个Pointcut:是一个AspectJExpressionPointcut。
该Advisor的语义拦截所有的方法名为hello的方法在它之前执行MyAspect.before1()方法。
如果我们现在需要创建一个代理对象,其需要绑定的Advisor逻辑跟上面定义的切面类中定义的Advisor类似。则我们可以进行如下编程:
代码语言:javascript复制 public static void main(String[] args) {
AspectJProxyFactory proxyFactory = new AspectJProxyFactory(new HelloServiceImpl());
// 注意:此处得MyAspect类上面的@Aspect注解必不可少
proxyFactory.addAspect(MyAspect.class);
//proxyFactory.setProxyTargetClass(true);//是否需要使用CGLIB代理
HelloService proxy = proxyFactory.getProxy();
proxy.hello();
System.out.println(proxy.getClass()); //class com.sun.proxy.$Proxy6
}
输出:
-----------before-----------
this is my method~~
class com.sun.proxy.$Proxy6
注意
- 需要注意的是在使用AspectjProxyFactory基于切面类创建代理对象时,我们指定的切面类上必须包含@Aspect注解。
- 虽然我们自己通过编程的方式可以通过AspectjProxyFactory创建基于@Aspect标注的切面类的代理,但是通过配置< aop:aspectj-autoproxy/ >(@EnableAspectJAutoProxy)使用基于注解的Aspectj风格的Aop时,Spring内部不是通过AspectjProxyFactory创建的代理对象,而是通过ProxyFactory
总结
这三个类本身没有什么关系,但都继承自:ProxyCreatorSupport,创建代理对象的核心逻辑都是在ProxyCreatorSupport中实现的
AspectJProxyFactory,ProxyFactoryBean,ProxyFactory 大体逻辑都是:
- 填充AdvisedSupport(ProxyCreatorSupport是其子类)的,然后交给父类ProxyCreatorSupport。
- 得到JDK或者CGLIB的AopProxy
- 代理调用时候被invoke或者intercept方法拦截(分别在JdkDynamicAopProxy和ObjenesisCglibAopProxy(CglibAopProxy的子类)的中)并且在这两个方法中调用AdvisedSupport的getInterceptorsAndDynamicInterceptionAdvice方法去初始化advice和各个方法直接映射关系并缓存