use of cn.taketoday.aop.TargetSource in project today-framework by TAKETODAY.
the class JdkDynamicAopProxy method invoke.
/**
* Implementation of {@code InvocationHandler.invoke}.
* <p>Callers will see exactly the exception thrown by the target,
* unless a hook method throws an exception.
*/
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = advised.getTargetSource();
Object target = null;
try {
if (!equalsDefined && ReflectionUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
} else if (!hashCodeDefined && ReflectionUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
} else {
Class<?> declaringClass = method.getDeclaringClass();
if (declaringClass == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
return AopProxyUtils.ultimateTargetClass(advised);
} else if (!advised.isOpaque()) {
if (declaringClass.isInterface() && declaringClass.isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
return AopUtils.invokeJoinpointUsingReflection(advised, method, args);
}
}
}
if (advised.isExposeProxy()) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target,
// in case it comes from a pool.
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// Get the interception chain for this method.
MethodInterceptor[] chain = advised.getInterceptors(method, targetClass);
Object retVal;
// reflective invocation of the target, and avoid creating a MethodInvocation.
if (ObjectUtils.isEmpty(chain)) {
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
Object[] argsToUse = ClassUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
} else {
// Proceed to the join-point through the interceptor chain.
retVal = new DefaultMethodInvocation(proxy, target, method, targetClass, args, chain).proceed();
}
// Massage return value if necessary
Class<?> returnType;
if (retVal != null && retVal == target && (returnType = method.getReturnType()) != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
retVal = proxy;
}
if (retVal == null) {
returnType = method.getReturnType();
if (returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException("Null return value from advice does not match primitive return type for: " + method);
}
}
return retVal;
} finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
use of cn.taketoday.aop.TargetSource in project today-framework by TAKETODAY.
the class StandardProxyInvoker method dynamicAdvisedProceed.
public static Object dynamicAdvisedProceed(Object proxy, AdvisedSupport advised, TargetInvocation targetInv, Object[] args) throws Throwable {
Object target = null;
Object oldProxy = null;
boolean restore = false;
final TargetSource targetSource = advised.getTargetSource();
try {
if (advised.isExposeProxy()) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
restore = true;
}
target = targetSource.getTarget();
final MethodInterceptor[] interceptors = targetInv.getDynamicInterceptors(advised);
// but just use MethodInvoker invocation of the target.
if (ObjectUtils.isEmpty(interceptors)) {
return targetInv.proceed(target, args);
}
// We need to create a DynamicStandardMethodInvocation...
final Object retVal = new DynamicStandardMethodInvocation(proxy, target, targetInv, args, interceptors).proceed();
assertReturnValue(retVal, targetInv.getMethod());
return retVal;
} finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (restore) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
use of cn.taketoday.aop.TargetSource in project today-framework by TAKETODAY.
the class MBeanServerConnectionFactoryBean method createLazyConnection.
/**
* Creates lazy proxies for the {@code JMXConnector} and {@code MBeanServerConnection}.
*/
private void createLazyConnection() {
this.connectorTargetSource = new JMXConnectorLazyInitTargetSource();
TargetSource connectionTargetSource = new MBeanServerConnectionLazyInitTargetSource();
this.connector = (JMXConnector) new ProxyFactory(JMXConnector.class, this.connectorTargetSource).getProxy(this.beanClassLoader);
this.connection = (MBeanServerConnection) new ProxyFactory(MBeanServerConnection.class, connectionTargetSource).getProxy(this.beanClassLoader);
}
use of cn.taketoday.aop.TargetSource in project today-framework by TAKETODAY.
the class AbstractAopProxyTests method testProxyIsBoundBeforeTargetSourceInvoked.
@Test
public void testProxyIsBoundBeforeTargetSourceInvoked() {
final TestBean target = new TestBean();
ProxyFactory pf = new ProxyFactory(target);
pf.addAdvice(new DebugInterceptor());
pf.setExposeProxy(true);
final ITestBean proxy = (ITestBean) createProxy(pf);
Advised config = (Advised) proxy;
// This class just checks proxy is bound before getTarget() call
config.setTargetSource(new TargetSource() {
@Override
public Class<?> getTargetClass() {
return TestBean.class;
}
@Override
public boolean isStatic() {
return false;
}
@Override
public Object getTarget() throws Exception {
assertThat(AopContext.currentProxy()).isEqualTo(proxy);
return target;
}
@Override
public void releaseTarget(Object target) throws Exception {
}
});
// Just test anything: it will fail if context wasn't found
assertThat(proxy.getAge()).isEqualTo(0);
}
use of cn.taketoday.aop.TargetSource in project today-framework by TAKETODAY.
the class ContextAnnotationAutowireCandidateResolver method buildLazyResolutionProxy.
protected Object buildLazyResolutionProxy(final DependencyDescriptor descriptor, @Nullable final String beanName) {
BeanFactory beanFactory = getBeanFactory();
Assert.state(beanFactory instanceof StandardBeanFactory, "BeanFactory needs to be a StandardBeanFactory");
final StandardBeanFactory dlbf = (StandardBeanFactory) beanFactory;
TargetSource ts = new TargetSource() {
@Override
public Class<?> getTargetClass() {
return descriptor.getDependencyType();
}
@Override
public boolean isStatic() {
return false;
}
@Override
public Object getTarget() {
Set<String> autowiredBeanNames = beanName != null ? new LinkedHashSet<>(1) : null;
Object target = dlbf.doResolveDependency(descriptor, beanName, autowiredBeanNames, null);
if (target == null) {
Class<?> type = getTargetClass();
if (Map.class == type) {
return Collections.emptyMap();
} else if (List.class == type) {
return Collections.emptyList();
} else if (Set.class == type || Collection.class == type) {
return Collections.emptySet();
}
throw new NoSuchBeanDefinitionException(descriptor.getResolvableType(), "Optional dependency not present for lazy injection point");
}
if (autowiredBeanNames != null) {
for (String autowiredBeanName : autowiredBeanNames) {
if (dlbf.containsBean(autowiredBeanName)) {
dlbf.registerDependentBean(autowiredBeanName, beanName);
}
}
}
return target;
}
@Override
public void releaseTarget(Object target) {
}
};
ProxyFactory pf = new ProxyFactory();
pf.setTargetSource(ts);
Class<?> dependencyType = descriptor.getDependencyType();
if (dependencyType.isInterface()) {
pf.addInterface(dependencyType);
}
return pf.getProxy(dlbf.getBeanClassLoader());
}
Aggregations