首页新闻找找看学习计划

AspectJProxyFactory 的getProxy() 方法

0
悬赏园豆:50 [已解决问题] 解决于 2017-03-20 19:10

Car proxy = factory.getProxy();

怎么做到将返回类型转为car的?

遁地龙卷风的主页 遁地龙卷风 | 初学一级 | 园豆:80
提问于:2017-03-20 16:34
< >
分享
最佳答案
1

你是如何构造 AspectJProxyFactory 的?

你应该是 

AspectJProxyFactory factory = new AspectJProxyFactory(Car .class);

Car proxy = factory.getProxy();

这样吧,你注意这里你把 Car的 class 传入了,通过java的反射,所以不需要强转。这个 factory 就只能用来构建Car类型的

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);
    }

AspectJProxyFactory 代码:

  1 /*
  2  * Copyright 2002-2015 the original author or authors.
  3  *
  4  * Licensed under the Apache License, Version 2.0 (the "License");
  5  * you may not use this file except in compliance with the License.
  6  * You may obtain a copy of the License at
  7  *
  8  *      http://www.apache.org/licenses/LICENSE-2.0
  9  *
 10  * Unless required by applicable law or agreed to in writing, software
 11  * distributed under the License is distributed on an "AS IS" BASIS,
 12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  * See the License for the specific language governing permissions and
 14  * limitations under the License.
 15  */
 16 
 17 package org.springframework.aop.aspectj.annotation;
 18 
 19 import java.util.HashMap;
 20 import java.util.List;
 21 import java.util.Map;
 22 
 23 import org.aspectj.lang.reflect.PerClauseKind;
 24 
 25 import org.springframework.aop.Advisor;
 26 import org.springframework.aop.aspectj.AspectJProxyUtils;
 27 import org.springframework.aop.framework.AopConfigException;
 28 import org.springframework.aop.framework.ProxyCreatorSupport;
 29 import org.springframework.aop.support.AopUtils;
 30 import org.springframework.core.annotation.AnnotationAwareOrderComparator;
 31 import org.springframework.util.Assert;
 32 import org.springframework.util.ClassUtils;
 33 
 34 /**
 35  * AspectJ-based proxy factory, allowing for programmatic building
 36  * of proxies which include AspectJ aspects (code style as well
 37  * Java 5 annotation style).
 38  *
 39  * @author Rob Harrop
 40  * @author Juergen Hoeller
 41  * @author Ramnivas Laddad
 42  * @since 2.0
 43  * @see #addAspect(Object)
 44  * @see #addAspect(Class)
 45  * @see #getProxy()
 46  * @see #getProxy(ClassLoader)
 47  * @see org.springframework.aop.framework.ProxyFactory
 48  */
 49 @SuppressWarnings("serial")
 50 public class AspectJProxyFactory extends ProxyCreatorSupport {
 51 
 52     /** Cache for singleton aspect instances */
 53     private static final Map<Class<?>, Object> aspectCache = new HashMap<Class<?>, Object>();
 54 
 55     private final AspectJAdvisorFactory aspectFactory = new ReflectiveAspectJAdvisorFactory();
 56 
 57 
 58     /**
 59      * Create a new AspectJProxyFactory.
 60      */
 61     public AspectJProxyFactory() {
 62     }
 63 
 64     /**
 65      * Create a new AspectJProxyFactory.
 66      * <p>Will proxy all interfaces that the given target implements.
 67      * @param target the target object to be proxied
 68      */
 69     public AspectJProxyFactory(Object target) {
 70         Assert.notNull(target, "Target object must not be null");
 71         setInterfaces(ClassUtils.getAllInterfaces(target));
 72         setTarget(target);
 73     }
 74 
 75     /**
 76      * Create a new {@code AspectJProxyFactory}.
 77      * No target, only interfaces. Must add interceptors.
 78      */
 79     public AspectJProxyFactory(Class<?>[] interfaces) {
 80         setInterfaces(interfaces);
 81     }
 82 
 83 
 84     /**
 85      * Add the supplied aspect instance to the chain. The type of the aspect instance
 86      * supplied must be a singleton aspect. True singleton lifecycle is not honoured when
 87      * using this method - the caller is responsible for managing the lifecycle of any
 88      * aspects added in this way.
 89      * @param aspectInstance the AspectJ aspect instance
 90      */
 91     public void addAspect(Object aspectInstance) {
 92         Class<?> aspectClass = aspectInstance.getClass();
 93         String aspectName = aspectClass.getName();
 94         AspectMetadata am = createAspectMetadata(aspectClass, aspectName);
 95         if (am.getAjType().getPerClause().getKind() != PerClauseKind.SINGLETON) {
 96             throw new IllegalArgumentException(
 97                     "Aspect class [" + aspectClass.getName() + "] does not define a singleton aspect");
 98         }
 99         addAdvisorsFromAspectInstanceFactory(
100                 new SingletonMetadataAwareAspectInstanceFactory(aspectInstance, aspectName));
101     }
102 
103     /**
104      * Add an aspect of the supplied type to the end of the advice chain.
105      * @param aspectClass the AspectJ aspect class
106      */
107     public void addAspect(Class<?> aspectClass) {
108         String aspectName = aspectClass.getName();
109         AspectMetadata am = createAspectMetadata(aspectClass, aspectName);
110         MetadataAwareAspectInstanceFactory instanceFactory = createAspectInstanceFactory(am, aspectClass, aspectName);
111         addAdvisorsFromAspectInstanceFactory(instanceFactory);
112     }
113 
114 
115     /**
116      * Add all {@link Advisor Advisors} from the supplied {@link MetadataAwareAspectInstanceFactory}
117      * to the current chain. Exposes any special purpose {@link Advisor Advisors} if needed.
118      * @see AspectJProxyUtils#makeAdvisorChainAspectJCapableIfNecessary(List)
119      */
120     private void addAdvisorsFromAspectInstanceFactory(MetadataAwareAspectInstanceFactory instanceFactory) {
121         List<Advisor> advisors = this.aspectFactory.getAdvisors(instanceFactory);
122         advisors = AopUtils.findAdvisorsThatCanApply(advisors, getTargetClass());
123         AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(advisors);
124         AnnotationAwareOrderComparator.sort(advisors);
125         addAdvisors(advisors);
126     }
127 
128     /**
129      * Create an {@link AspectMetadata} instance for the supplied aspect type.
130      */
131     private AspectMetadata createAspectMetadata(Class<?> aspectClass, String aspectName) {
132         AspectMetadata am = new AspectMetadata(aspectClass, aspectName);
133         if (!am.getAjType().isAspect()) {
134             throw new IllegalArgumentException("Class [" + aspectClass.getName() + "] is not a valid aspect type");
135         }
136         return am;
137     }
138 
139     /**
140      * Create a {@link MetadataAwareAspectInstanceFactory} for the supplied aspect type. If the aspect type
141      * has no per clause, then a {@link SingletonMetadataAwareAspectInstanceFactory} is returned, otherwise
142      * a {@link PrototypeAspectInstanceFactory} is returned.
143      */
144     private MetadataAwareAspectInstanceFactory createAspectInstanceFactory(
145             AspectMetadata am, Class<?> aspectClass, String aspectName) {
146 
147         MetadataAwareAspectInstanceFactory instanceFactory = null;
148         if (am.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
149             // Create a shared aspect instance.
150             Object instance = getSingletonAspectInstance(aspectClass);
151             instanceFactory = new SingletonMetadataAwareAspectInstanceFactory(instance, aspectName);
152         }
153         else {
154             // Create a factory for independent aspect instances.
155             instanceFactory = new SimpleMetadataAwareAspectInstanceFactory(aspectClass, aspectName);
156         }
157         return instanceFactory;
158     }
159 
160     /**
161      * Get the singleton aspect instance for the supplied aspect type. An instance
162      * is created if one cannot be found in the instance cache.
163      */
164     private Object getSingletonAspectInstance(Class<?> aspectClass) {
165         synchronized (aspectCache) {
166             Object instance = aspectCache.get(aspectClass);
167             if (instance != null) {
168                 return instance;
169             }
170             try {
171                 instance = aspectClass.newInstance();
172                 aspectCache.put(aspectClass, instance);
173                 return instance;
174             }
175             catch (InstantiationException ex) {
176                 throw new AopConfigException("Unable to instantiate aspect class [" + aspectClass.getName() + "]", ex);
177             }
178             catch (IllegalAccessException ex) {
179                 throw new AopConfigException("Cannot access aspect class [" + aspectClass.getName() + "]", ex);
180             }
181         }
182     }
183 
184 
185     /**
186      * Create a new proxy according to the settings in this factory.
187      * <p>Can be called repeatedly. Effect will vary if we've added
188      * or removed interfaces. Can add and remove interceptors.
189      * <p>Uses a default class loader: Usually, the thread context class loader
190      * (if necessary for proxy creation).
191      * @return the new proxy
192      */
193     @SuppressWarnings("unchecked")
194     public <T> T getProxy() {
195         return (T) createAopProxy().getProxy();
196     }
197 
198     /**
199      * Create a new proxy according to the settings in this factory.
200      * <p>Can be called repeatedly. Effect will vary if we've added
201      * or removed interfaces. Can add and remove interceptors.
202      * <p>Uses the given class loader (if necessary for proxy creation).
203      * @param classLoader the class loader to create the proxy with
204      * @return the new proxy
205      */
206     @SuppressWarnings("unchecked")
207     public <T> T getProxy(ClassLoader classLoader) {
208         return (T) createAopProxy().getProxy(classLoader);
209     }
210 
211 }
AspectJProxyFactory.java
收获园豆:50
蜀黎peng | 菜鸟二级 |园豆:323 | 2017-03-20 19:04

问题就在这 “通过java的反射,所以不需要强转”,这个反射代码是如何写的呢?

遁地龙卷风 | 园豆:80 (初学一级) | 2017-03-20 19:07

@遁地龙卷风: 看构造函数的第三行代码:setTarget(target);

这个是在父类定义的:

 1 /**
 2 * Set the given object as target. 设置所给的对象作为目标对象
 3 * Will create a SingletonTargetSource for the object.
 4 * @see #setTargetSource
 5 * @see org.springframework.aop.target.SingletonTargetSource
 6 */
 7 public void setTarget(Object target) {
 8 setTargetSource(new SingletonTargetSource(target));
 9 }
蜀黎peng | 园豆:323 (菜鸟二级) | 2017-03-20 19:57

@遁地龙卷风: http://www.tuicool.com/articles/fEFrInJ 这里是 TargetSource 的介绍

蜀黎peng | 园豆:323 (菜鸟二级) | 2017-03-20 20:01
其他回答(1)
0

Car proxy = (Car)factory.getProxy();

沙隐泉 | 园豆:210 (菜鸟二级) | 2017-03-20 16:49

Car proxy = factory.getProxy();  没用强制转换,源码就是这样

支持(0) 反对(0) 遁地龙卷风 | 园豆:80 (初学一级) | 2017-03-20 16:51

@遁地龙卷风: 你是问它是怎么做到直接得到car而不需要转换吗?

可以查看到getProxy()的封装代码吗?

支持(0) 反对(0) 沙隐泉 | 园豆:210 (菜鸟二级) | 2017-03-20 16:57
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册