📄 proxyfactorybean.java
字号:
private synchronized Object newPrototypeInstance() {
refreshAdvisorChain();
refreshTarget();
// In the case of a prototype, we need to give the proxy
// an independent instance of the configuration.
if (logger.isDebugEnabled()) {
logger.debug("Creating copy of prototype ProxyFactoryBean config: " + this);
}
AdvisedSupport copy = new AdvisedSupport();
copy.copyConfigurationFrom(this);
if (logger.isDebugEnabled()) {
logger.debug("Copy has config: " + copy);
}
return copy.createAopProxy().getProxy();
}
/**
* Create the advisor (interceptor) chain. The advisors that are sourced
* from a BeanFactory will be refreshed each time a new prototype instance
* is added. Interceptors added programmatically through the factory API
* are unaffected by such changes.
*/
private void createAdvisorChain() throws AopConfigException, BeansException {
if (this.interceptorNames == null || this.interceptorNames.length == 0) {
return;
}
// Globals can't be last
if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX)) {
throw new AopConfigException("Target required after globals");
}
// Materialize interceptor chain from bean names
for (int i = 0; i < this.interceptorNames.length; i++) {
String name = this.interceptorNames[i];
logger.debug("Configuring interceptor '" + name + "'");
if (name.endsWith(GLOBAL_SUFFIX)) {
if (!(this.beanFactory instanceof ListableBeanFactory)) {
throw new AopConfigException("Can only use global advisors or interceptors with a ListableBeanFactory");
}
else {
addGlobalAdvisor((ListableBeanFactory) this.beanFactory,
name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
}
}
else {
// add a named interceptor
Object advice = this.beanFactory.getBean(this.interceptorNames[i]);
addAdvisor(advice, this.interceptorNames[i]);
}
}
}
/**
* Refresh named beans from the interceptor chain.
* We need to do this every time a new prototype instance is returned,
* to return distinct instances of prototype interfaces and pointcuts.
*/
private void refreshAdvisorChain() {
Advisor[] advisors = getAdvisors();
for (int i = 0; i < advisors.length; i++) {
String beanName = (String) this.sourceMap.get(advisors[i]);
if (beanName != null) {
logger.info("Refreshing bean named '" + beanName + "'");
Object bean = this.beanFactory.getBean(beanName);
Object refreshedAdvisor = namedBeanToAdvisorOrTargetSource(bean);
// might have just refreshed target source
if (refreshedAdvisor instanceof Advisor) {
// What about aspect interfaces!? we're only updating
replaceAdvisor(advisors[i], (Advisor) refreshedAdvisor);
}
else {
setTargetSource((TargetSource) refreshedAdvisor);
}
// keep name mapping up to date
this.sourceMap.put(refreshedAdvisor, beanName);
}
else {
// We can't throw an exception here, as the user may have added additional
// pointcuts programmatically we don't know about
logger.info("Cannot find bean name for Advisor [" + advisors[i] +
"] when refreshing advisor chain");
}
}
}
/**
* Add all global interceptors and pointcuts.
*/
private void addGlobalAdvisor(ListableBeanFactory beanFactory, String prefix) {
String[] globalAdvisorNames = BeanFactoryUtils.beanNamesIncludingAncestors(beanFactory, Advisor.class);
String[] globalInterceptorNames = BeanFactoryUtils.beanNamesIncludingAncestors(beanFactory, Interceptor.class);
List beans = new ArrayList(globalAdvisorNames.length + globalInterceptorNames.length);
Map names = new HashMap();
for (int i = 0; i < globalAdvisorNames.length; i++) {
String name = globalAdvisorNames[i];
Object bean = beanFactory.getBean(name);
beans.add(bean);
names.put(bean, name);
}
for (int i = 0; i < globalInterceptorNames.length; i++) {
String name = globalInterceptorNames[i];
Object bean = beanFactory.getBean(name);
beans.add(bean);
names.put(bean, name);
}
Collections.sort(beans, new OrderComparator());
for (Iterator it = beans.iterator(); it.hasNext();) {
Object bean = it.next();
String name = (String) names.get(bean);
if (name.startsWith(prefix)) {
addAdvisor(bean, name);
}
}
}
/**
* Add the given interceptor, pointcut or object to the interceptor list.
* Because of these three possibilities, we can't type the signature
* more strongly.
* @param next interceptor, pointcut or target object.
* @param name bean name from which we obtained this object in our owning
* bean factory
*/
private void addAdvisor(Object next, String name) {
logger.debug("Adding advisor or TargetSource [" + next + "] with name [" + name + "]");
// We need to add a method pointcut so that our source reference matches
// what we find from superclass interceptors.
Object advisor = namedBeanToAdvisorOrTargetSource(next);
if (advisor instanceof Advisor) {
// if it wasn't just updating the TargetSource
logger.debug("Adding advisor with name [" + name + "]");
addAdvisor((Advisor) advisor);
// Record the pointcut as descended from the given bean name.
// This allows us to refresh the interceptor list, which we'll need to
// do if we have to create a new prototype instance. Otherwise the new
// prototype instance wouldn't be truly independent, because it might
// reference the original instances of prototype interceptors.
this.sourceMap.put(advisor, name);
}
else {
logger.debug("Adding TargetSource [" + advisor + "] with name [" + name + "]");
setTargetSource((TargetSource) advisor);
// save target name
this.targetName = name;
}
}
private void refreshTarget() {
logger.debug("Refreshing target with name '" + this.targetName + "'");
if (this.targetName == null) {
throw new AopConfigException("Target name cannot be null when refreshing!");
}
Object target = this.beanFactory.getBean(this.targetName);
setTarget(target);
}
/**
* Return Advisor or TargetSource.
*/
private Object namedBeanToAdvisorOrTargetSource(Object next) {
try {
Advisor adv = GlobalAdvisorAdapterRegistry.getInstance().wrap(next);
return adv;
}
catch (UnknownAdviceTypeException ex) {
// TODO consider checking that it's the last in the list?
if (next instanceof TargetSource) {
return (TargetSource) next;
}
else {
// It's not a pointcut or interceptor.
// It's a bean that needs an invoker around it.
return new SingletonTargetSource(next);
}
}
}
/**
* @see org.springframework.aop.framework.AdvisedSupportListener#activated(org.springframework.aop.framework.AdvisedSupport)
*/
public void activated(AdvisedSupport advisedSupport) {
}
/**
* Blow away and recache singleton to allow for advice changes.
* @see org.springframework.aop.framework.AdvisedSupportListener#adviceChanged(org.springframework.aop.framework.AdvisedSupport)
*/
public void adviceChanged(AdvisedSupport advisedSupport) {
logger.info("Advice has changed; recaching singleton instance");
this.singletonInstance = null;
getSingletonInstance();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -