spring aop 自動建立代理BeanNameAutoProxyCreator詳解
程式碼示例
<?xml version=”1.0” encoding=”UTF-8”?>
<beans xmlns=”http://www.springframework.org/schema/beans”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xmlns:aop=”http://www.springframework.org/schema/aop”
xmlns:context=”http://www.springframework.org/schema/context”
xmlns:util=”http://www.springframework.org/schema/util”
xsi:schemaLocation=”
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-4.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.2.xsd“>
<context:component-scan base-package=”org.bear.bookstore.test.aop”></context:component-scan>
<!– 自動建立代理 –>
<bean class=”org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator”>
<property name=”beanNames”><value>aopS*</value></property>
<property name=”interceptorNames”>
<list>
<value>debugInterceptor</value>
</list>
</property>
</bean>
</beans>
@Component("aopService")
public class AopService {
public void set(String name){
System.out.println(name);
}
}
```
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
locations={"file:src/test/resources/spring-aop.xml"}
)
public class AopTest {
@Autowired ApplicationContext ctx;
//@Test
public void debugTest(){
AopService ser = (AopService)ctx.getBean("proxyFactory");
ser.set("zh");
}
@Autowired AopService aopService;
@Test
public void debug1Test(){
aopService.set("zh11");
}
}
aopService.set(“zh11”);執行這一句前後spring幹了什麼事情
剖析
看到BeanPostProcessor後,心安了,知道咱們配置的BeanNameAutoProxyCreator是什麼時候執行什麼樣的方法了
BeanNameAutoProxyCreator.getAdvicesAndAdvisorsForBean決定是否需要建立代理,通過names過濾
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
if (this.beanNames != null) {
for (String mappedName : this.beanNames) {
if (FactoryBean.class.isAssignableFrom(beanClass)) {
if (!mappedName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
continue;
}
mappedName = mappedName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
if (isMatch(beanName, mappedName)) {
return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
}
BeanFactory beanFactory = getBeanFactory();
if (beanFactory != null) {
String[] aliases = beanFactory.getAliases(beanName);
for (String alias : aliases) {
if (isMatch(alias, mappedName)) {
return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
}
}
}
}
}
return DO_NOT_PROXY;
}
AbstractAutoProxyCreator.wrapIfNecessary方法,暴露是否需要建立代理的方法供子類使用
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 是否需要建立代理
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//關鍵建立代理的地方
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
AbstractAutoProxyCreator.createProxy方法建立代理的準備工作
protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
//AopProxyUtils
/**
* Bean definition attribute that indicates the original target class of an
* auto-proxied bean, e.g. to be used for the introspection of annotations
* on the target class behind an interface-based proxy.
* @since 4.2.3
* @see #determineTargetClass
*/
/*public static final String ORIGINAL_TARGET_CLASS_ATTRIBUTE =
Conventions.getQualifiedAttributeName(AutoProxyUtils.class, "originalTargetClass");*/
//儲存代理類真實的型別org.springframework.beans.factory.BeanFactory#getType(String)用
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
//初始化advisor,也就是interceptorNames
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
for (Advisor advisor : advisors) {
proxyFactory.addAdvisor(advisor);
}
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
//真正建立代理方法
return proxyFactory.getProxy(getProxyClassLoader());
}
public Object getProxy(ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
/**
* Subclasses should call this to get a new AOP proxy. They should <b>not</b>
* create an AOP proxy with {@code this} as an argument.
*/
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
//DefaultAopProxyFactory
@Override
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.");
}
//如果是介面類或者代理類則通過jdk動態代理來實現
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
//最後用的就是Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
return new JdkDynamicAopProxy(config);
}
//用的就是使用的Cglib了
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
初始化完成後,執行aopService.set(“zh11”)時就是呼叫代理後的方法了,就跟責任鏈差不多了