Refactor method name dispatching to switch statements

Closes gh-25163
This commit is contained in:
Juergen Hoeller 2020-05-29 23:07:25 +02:00
parent 7207f7645c
commit e955e52f2f
15 changed files with 499 additions and 547 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -185,26 +185,25 @@ final class SerializableTypeWrapper {
@Override
@Nullable
public Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable {
if (method.getName().equals("equals") && args != null) {
Object other = args[0];
// Unwrap proxies for speed
if (other instanceof Type) {
other = unwrap((Type) other);
}
return ObjectUtils.nullSafeEquals(this.provider.getType(), other);
}
else if (method.getName().equals("hashCode")) {
return ObjectUtils.nullSafeHashCode(this.provider.getType());
}
else if (method.getName().equals("getTypeProvider")) {
return this.provider;
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
switch (method.getName()) {
case "equals":
Object other = args[0];
// Unwrap proxies for speed
if (other instanceof Type) {
other = unwrap((Type) other);
}
return ObjectUtils.nullSafeEquals(this.provider.getType(), other);
case "hashCode":
return ObjectUtils.nullSafeHashCode(this.provider.getType());
case "getTypeProvider":
return this.provider;
}
if (Type.class == method.getReturnType() && args == null) {
if (Type.class == method.getReturnType() && ObjectUtils.isEmpty(args)) {
return forTypeProvider(new MethodInvokeTypeProvider(this.provider, method, -1));
}
else if (Type[].class == method.getReturnType() && args == null) {
else if (Type[].class == method.getReturnType() && ObjectUtils.isEmpty(args)) {
Type[] result = new Type[((Type[]) method.invoke(this.provider.getType())).length];
for (int i = 0; i < result.length; i++) {
result[i] = forTypeProvider(new MethodInvokeTypeProvider(this.provider, method, i));

View File

@ -1581,34 +1581,25 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Invocation on ConnectionProxy interface coming in...
if (method.getName().equals("equals")) {
// Only consider equal when proxies are identical.
return (proxy == args[0]);
}
else if (method.getName().equals("hashCode")) {
// Use hashCode of PersistenceManager proxy.
return System.identityHashCode(proxy);
}
else if (method.getName().equals("unwrap")) {
if (((Class<?>) args[0]).isInstance(proxy)) {
return proxy;
}
}
else if (method.getName().equals("isWrapperFor")) {
if (((Class<?>) args[0]).isInstance(proxy)) {
return true;
}
}
else if (method.getName().equals("close")) {
// Handle close method: suppress, not valid.
return null;
}
else if (method.getName().equals("isClosed")) {
return false;
}
else if (method.getName().equals("getTargetConnection")) {
// Handle getTargetConnection method: return underlying Connection.
return this.target;
switch (method.getName()) {
case "equals":
// Only consider equal when proxies are identical.
return (proxy == args[0]);
case "hashCode":
// Use hashCode of PersistenceManager proxy.
return System.identityHashCode(proxy);
case "close":
// Handle close method: suppress, not valid.
return null;
case "isClosed":
return false;
case "getTargetConnection":
// Handle getTargetConnection method: return underlying Connection.
return this.target;
case "unwrap":
return (((Class<?>) args[0]).isInstance(proxy) ? proxy : this.target.unwrap((Class<?>) args[0]));
case "isWrapperFor":
return (((Class<?>) args[0]).isInstance(proxy) || this.target.isWrapperFor((Class<?>) args[0]));
}
// Invoke method on target Connection.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -285,30 +285,29 @@ public class LazyConnectionDataSourceProxy extends DelegatingDataSource {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Invocation on ConnectionProxy interface coming in...
if (method.getName().equals("equals")) {
// We must avoid fetching a target Connection for "equals".
// Only consider equal when proxies are identical.
return (proxy == args[0]);
}
else if (method.getName().equals("hashCode")) {
// We must avoid fetching a target Connection for "hashCode",
// and we must return the same hash code even when the target
// Connection has been fetched: use hashCode of Connection proxy.
return System.identityHashCode(proxy);
}
else if (method.getName().equals("unwrap")) {
if (((Class<?>) args[0]).isInstance(proxy)) {
return proxy;
}
}
else if (method.getName().equals("isWrapperFor")) {
if (((Class<?>) args[0]).isInstance(proxy)) {
return true;
}
}
else if (method.getName().equals("getTargetConnection")) {
// Handle getTargetConnection method: return underlying connection.
return getTargetConnection(method);
switch (method.getName()) {
case "equals":
// We must avoid fetching a target Connection for "equals".
// Only consider equal when proxies are identical.
return (proxy == args[0]);
case "hashCode":
// We must avoid fetching a target Connection for "hashCode",
// and we must return the same hash code even when the target
// Connection has been fetched: use hashCode of Connection proxy.
return System.identityHashCode(proxy);
case "getTargetConnection":
// Handle getTargetConnection method: return underlying connection.
return getTargetConnection(method);
case "unwrap":
if (((Class<?>) args[0]).isInstance(proxy)) {
return proxy;
}
break;
case "isWrapperFor":
if (((Class<?>) args[0]).isInstance(proxy)) {
return true;
}
break;
}
if (!hasTargetConnection()) {
@ -316,65 +315,59 @@ public class LazyConnectionDataSourceProxy extends DelegatingDataSource {
// resolve transaction demarcation methods without fetching
// a physical JDBC Connection until absolutely necessary.
if (method.getName().equals("toString")) {
return "Lazy Connection proxy for target DataSource [" + getTargetDataSource() + "]";
}
else if (method.getName().equals("getAutoCommit")) {
if (this.autoCommit != null) {
return this.autoCommit;
}
// Else fetch actual Connection and check there,
// because we didn't have a default specified.
}
else if (method.getName().equals("setAutoCommit")) {
this.autoCommit = (Boolean) args[0];
return null;
}
else if (method.getName().equals("getTransactionIsolation")) {
if (this.transactionIsolation != null) {
return this.transactionIsolation;
}
// Else fetch actual Connection and check there,
// because we didn't have a default specified.
}
else if (method.getName().equals("setTransactionIsolation")) {
this.transactionIsolation = (Integer) args[0];
return null;
}
else if (method.getName().equals("isReadOnly")) {
return this.readOnly;
}
else if (method.getName().equals("setReadOnly")) {
this.readOnly = (Boolean) args[0];
return null;
}
else if (method.getName().equals("getHoldability")) {
return this.holdability;
}
else if (method.getName().equals("setHoldability")) {
this.holdability = (Integer) args[0];
return null;
}
else if (method.getName().equals("commit") || method.getName().equals("rollback")) {
// Ignore: no statements created yet.
return null;
}
else if (method.getName().equals("getWarnings") || method.getName().equals("clearWarnings")) {
// Ignore: no warnings to expose yet.
return null;
}
else if (method.getName().equals("close")) {
// Ignore: no target connection yet.
this.closed = true;
return null;
}
else if (method.getName().equals("isClosed")) {
return this.closed;
}
else if (this.closed) {
// Connection proxy closed, without ever having fetched a
// physical JDBC Connection: throw corresponding SQLException.
throw new SQLException("Illegal operation: connection is closed");
switch (method.getName()) {
case "toString":
return "Lazy Connection proxy for target DataSource [" + getTargetDataSource() + "]";
case "getAutoCommit":
if (this.autoCommit != null) {
return this.autoCommit;
}
// Else fetch actual Connection and check there,
// because we didn't have a default specified.
break;
case "setAutoCommit":
this.autoCommit = (Boolean) args[0];
return null;
case "getTransactionIsolation":
if (this.transactionIsolation != null) {
return this.transactionIsolation;
}
// Else fetch actual Connection and check there,
// because we didn't have a default specified.
break;
case "setTransactionIsolation":
this.transactionIsolation = (Integer) args[0];
return null;
case "isReadOnly":
return this.readOnly;
case "setReadOnly":
this.readOnly = (Boolean) args[0];
return null;
case "getHoldability":
return this.holdability;
case "setHoldability":
this.holdability = (Integer) args[0];
return null;
case "commit":
case "rollback":
// Ignore: no statements created yet.
return null;
case "getWarnings":
case "clearWarnings":
// Ignore: no warnings to expose yet.
return null;
case "close":
// Ignore: no target connection yet.
this.closed = true;
return null;
case "isClosed":
return this.closed;
default:
if (this.closed) {
// Connection proxy closed, without ever having fetched a
// physical JDBC Connection: throw corresponding SQLException.
throw new SQLException("Illegal operation: connection is closed");
}
}
}

View File

@ -299,34 +299,25 @@ public class SingleConnectionDataSource extends DriverManagerDataSource implemen
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Invocation on ConnectionProxy interface coming in...
if (method.getName().equals("equals")) {
// Only consider equal when proxies are identical.
return (proxy == args[0]);
}
else if (method.getName().equals("hashCode")) {
// Use hashCode of Connection proxy.
return System.identityHashCode(proxy);
}
else if (method.getName().equals("unwrap")) {
if (((Class<?>) args[0]).isInstance(proxy)) {
return proxy;
}
}
else if (method.getName().equals("isWrapperFor")) {
if (((Class<?>) args[0]).isInstance(proxy)) {
return true;
}
}
else if (method.getName().equals("close")) {
// Handle close method: don't pass the call on.
return null;
}
else if (method.getName().equals("isClosed")) {
return this.target.isClosed();
}
else if (method.getName().equals("getTargetConnection")) {
// Handle getTargetConnection method: return underlying Connection.
return this.target;
switch (method.getName()) {
case "equals":
// Only consider equal when proxies are identical.
return (proxy == args[0]);
case "hashCode":
// Use hashCode of Connection proxy.
return System.identityHashCode(proxy);
case "close":
// Handle close method: don't pass the call on.
return null;
case "isClosed":
return this.target.isClosed();
case "getTargetConnection":
// Handle getTargetConnection method: return underlying Connection.
return this.target;
case "unwrap":
return (((Class<?>) args[0]).isInstance(proxy) ? proxy : this.target.unwrap((Class<?>) args[0]));
case "isWrapperFor":
return (((Class<?>) args[0]).isInstance(proxy) || this.target.isWrapperFor((Class<?>) args[0]));
}
// Invoke method on target Connection.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -175,43 +175,40 @@ public class TransactionAwareDataSourceProxy extends DelegatingDataSource {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Invocation on ConnectionProxy interface coming in...
if (method.getName().equals("equals")) {
// Only considered as equal when proxies are identical.
return (proxy == args[0]);
}
else if (method.getName().equals("hashCode")) {
// Use hashCode of Connection proxy.
return System.identityHashCode(proxy);
}
else if (method.getName().equals("toString")) {
// Allow for differentiating between the proxy and the raw Connection.
StringBuilder sb = new StringBuilder("Transaction-aware proxy for target Connection ");
if (this.target != null) {
sb.append("[").append(this.target.toString()).append("]");
}
else {
sb.append(" from DataSource [").append(this.targetDataSource).append("]");
}
return sb.toString();
}
else if (method.getName().equals("unwrap")) {
if (((Class<?>) args[0]).isInstance(proxy)) {
return proxy;
}
}
else if (method.getName().equals("isWrapperFor")) {
if (((Class<?>) args[0]).isInstance(proxy)) {
return true;
}
}
else if (method.getName().equals("close")) {
// Handle close method: only close if not within a transaction.
DataSourceUtils.doReleaseConnection(this.target, this.targetDataSource);
this.closed = true;
return null;
}
else if (method.getName().equals("isClosed")) {
return this.closed;
switch (method.getName()) {
case "equals":
// Only considered as equal when proxies are identical.
return (proxy == args[0]);
case "hashCode":
// Use hashCode of Connection proxy.
return System.identityHashCode(proxy);
case "toString":
// Allow for differentiating between the proxy and the raw Connection.
StringBuilder sb = new StringBuilder("Transaction-aware proxy for target Connection ");
if (this.target != null) {
sb.append("[").append(this.target.toString()).append("]");
}
else {
sb.append(" from DataSource [").append(this.targetDataSource).append("]");
}
return sb.toString();
case "close":
// Handle close method: only close if not within a transaction.
DataSourceUtils.doReleaseConnection(this.target, this.targetDataSource);
this.closed = true;
return null;
case "isClosed":
return this.closed;
case "unwrap":
if (((Class<?>) args[0]).isInstance(proxy)) {
return proxy;
}
break;
case "isWrapperFor":
if (((Class<?>) args[0]).isInstance(proxy)) {
return true;
}
break;
}
if (this.target == null) {

View File

@ -44,6 +44,7 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
/**
* A JMS ConnectionFactory adapter that returns the same Connection
@ -543,124 +544,118 @@ public class SingleConnectionFactory implements ConnectionFactory, QueueConnecti
@Override
@Nullable
public Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable {
if (method.getName().equals("equals") && args != null) {
Object other = args[0];
if (proxy == other) {
return true;
}
if (other == null || !Proxy.isProxyClass(other.getClass())) {
return false;
}
InvocationHandler otherHandler = Proxy.getInvocationHandler(other);
return (otherHandler instanceof SharedConnectionInvocationHandler &&
factory() == ((SharedConnectionInvocationHandler) otherHandler).factory());
}
else if (method.getName().equals("hashCode")) {
// Use hashCode of containing SingleConnectionFactory.
return System.identityHashCode(factory());
}
else if (method.getName().equals("toString")) {
return "Shared JMS Connection: " + getConnection();
}
else if (method.getName().equals("setClientID") && args != null) {
// Handle setClientID method: throw exception if not compatible.
String currentClientId = getConnection().getClientID();
if (currentClientId != null && currentClientId.equals(args[0])) {
return null;
}
else {
throw new javax.jms.IllegalStateException(
"setClientID call not supported on proxy for shared Connection. " +
"Set the 'clientId' property on the SingleConnectionFactory instead.");
}
}
else if (method.getName().equals("setExceptionListener") && args != null) {
// Handle setExceptionListener method: add to the chain.
synchronized (connectionMonitor) {
if (aggregatedExceptionListener != null) {
ExceptionListener listener = (ExceptionListener) args[0];
if (listener != this.localExceptionListener) {
if (this.localExceptionListener != null) {
aggregatedExceptionListener.delegates.remove(this.localExceptionListener);
}
if (listener != null) {
aggregatedExceptionListener.delegates.add(listener);
}
this.localExceptionListener = listener;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
switch (method.getName()) {
case "equals":
Object other = args[0];
if (proxy == other) {
return true;
}
if (other == null || !Proxy.isProxyClass(other.getClass())) {
return false;
}
InvocationHandler otherHandler = Proxy.getInvocationHandler(other);
return (otherHandler instanceof SharedConnectionInvocationHandler &&
factory() == ((SharedConnectionInvocationHandler) otherHandler).factory());
case "hashCode":
// Use hashCode of containing SingleConnectionFactory.
return System.identityHashCode(factory());
case "toString":
return "Shared JMS Connection: " + getConnection();
case "setClientID":
// Handle setClientID method: throw exception if not compatible.
String currentClientId = getConnection().getClientID();
if (currentClientId != null && currentClientId.equals(args[0])) {
return null;
}
else {
throw new javax.jms.IllegalStateException(
"setExceptionListener call not supported on proxy for shared Connection. " +
"Set the 'exceptionListener' property on the SingleConnectionFactory instead. " +
"Alternatively, activate SingleConnectionFactory's 'reconnectOnException' feature, " +
"which will allow for registering further ExceptionListeners to the recovery chain.");
"setClientID call not supported on proxy for shared Connection. " +
"Set the 'clientId' property on the SingleConnectionFactory instead.");
}
}
}
else if (method.getName().equals("getExceptionListener")) {
synchronized (connectionMonitor) {
if (this.localExceptionListener != null) {
return this.localExceptionListener;
}
else {
return getExceptionListener();
}
}
}
else if (method.getName().equals("start")) {
localStart();
return null;
}
else if (method.getName().equals("stop")) {
localStop();
return null;
}
else if (method.getName().equals("close")) {
localStop();
synchronized (connectionMonitor) {
if (this.localExceptionListener != null) {
case "setExceptionListener":
// Handle setExceptionListener method: add to the chain.
synchronized (connectionMonitor) {
if (aggregatedExceptionListener != null) {
aggregatedExceptionListener.delegates.remove(this.localExceptionListener);
ExceptionListener listener = (ExceptionListener) args[0];
if (listener != this.localExceptionListener) {
if (this.localExceptionListener != null) {
aggregatedExceptionListener.delegates.remove(this.localExceptionListener);
}
if (listener != null) {
aggregatedExceptionListener.delegates.add(listener);
}
this.localExceptionListener = listener;
}
return null;
}
else {
throw new javax.jms.IllegalStateException(
"setExceptionListener call not supported on proxy for shared Connection. " +
"Set the 'exceptionListener' property on the SingleConnectionFactory instead. " +
"Alternatively, activate SingleConnectionFactory's 'reconnectOnException' feature, " +
"which will allow for registering further ExceptionListeners to the recovery chain.");
}
this.localExceptionListener = null;
}
}
return null;
}
else if (method.getName().equals("createSession") || method.getName().equals("createQueueSession") ||
method.getName().equals("createTopicSession")) {
// Default: JMS 2.0 createSession() method
Integer mode = Session.AUTO_ACKNOWLEDGE;
if (args != null) {
if (args.length == 1) {
// JMS 2.0 createSession(int) method
mode = (Integer) args[0];
}
else if (args.length == 2) {
// JMS 1.1 createSession(boolean, int) method
boolean transacted = (Boolean) args[0];
Integer ackMode = (Integer) args[1];
mode = (transacted ? Session.SESSION_TRANSACTED : ackMode);
}
}
Session session = getSession(getConnection(), mode);
if (session != null) {
if (!method.getReturnType().isInstance(session)) {
String msg = "JMS Session does not implement specific domain: " + session;
try {
session.close();
}
catch (Throwable ex) {
logger.trace("Failed to close newly obtained JMS Session", ex);
}
throw new javax.jms.IllegalStateException(msg);
}
return session;
}
case "getExceptionListener":
synchronized (connectionMonitor) {
if (this.localExceptionListener != null) {
return this.localExceptionListener;
}
else {
return getExceptionListener();
}
}
case "start":
localStart();
return null;
case "stop":
localStop();
return null;
case "close":
localStop();
synchronized (connectionMonitor) {
if (this.localExceptionListener != null) {
if (aggregatedExceptionListener != null) {
aggregatedExceptionListener.delegates.remove(this.localExceptionListener);
}
this.localExceptionListener = null;
}
}
return null;
case "createSession":
case "createQueueSession":
case "createTopicSession":
// Default: JMS 2.0 createSession() method
Integer mode = Session.AUTO_ACKNOWLEDGE;
if (!ObjectUtils.isEmpty(args)) {
if (args.length == 1) {
// JMS 2.0 createSession(int) method
mode = (Integer) args[0];
}
else if (args.length == 2) {
// JMS 1.1 createSession(boolean, int) method
boolean transacted = (Boolean) args[0];
Integer ackMode = (Integer) args[1];
mode = (transacted ? Session.SESSION_TRANSACTED : ackMode);
}
}
Session session = getSession(getConnection(), mode);
if (session != null) {
if (!method.getReturnType().isInstance(session)) {
String msg = "JMS Session does not implement specific domain: " + session;
try {
session.close();
}
catch (Throwable ex) {
logger.trace("Failed to close newly obtained JMS Session", ex);
}
throw new javax.jms.IllegalStateException(msg);
}
return session;
}
}
try {
return method.invoke(getConnection(), args);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -256,15 +256,16 @@ public class TransactionAwareConnectionFactoryProxy
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Invocation on ConnectionProxy interface coming in...
if (method.getName().equals("equals")) {
// Only consider equal when proxies are identical.
return (proxy == args[0]);
switch (method.getName()) {
case "equals":
// Only consider equal when proxies are identical.
return (proxy == args[0]);
case "hashCode":
// Use hashCode of Connection proxy.
return System.identityHashCode(proxy);
}
else if (method.getName().equals("hashCode")) {
// Use hashCode of Connection proxy.
return System.identityHashCode(proxy);
}
else if (Session.class == method.getReturnType()) {
if (Session.class == method.getReturnType()) {
Session session = ConnectionFactoryUtils.getTransactionalSession(
getTargetConnectionFactory(), this.target, isSynchedLocalTransactionAllowed());
if (session != null) {
@ -328,27 +329,23 @@ public class TransactionAwareConnectionFactoryProxy
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Invocation on SessionProxy interface coming in...
if (method.getName().equals("equals")) {
// Only consider equal when proxies are identical.
return (proxy == args[0]);
}
else if (method.getName().equals("hashCode")) {
// Use hashCode of Connection proxy.
return System.identityHashCode(proxy);
}
else if (method.getName().equals("commit")) {
throw new TransactionInProgressException("Commit call not allowed within a managed transaction");
}
else if (method.getName().equals("rollback")) {
throw new TransactionInProgressException("Rollback call not allowed within a managed transaction");
}
else if (method.getName().equals("close")) {
// Handle close method: not to be closed within a transaction.
return null;
}
else if (method.getName().equals("getTargetSession")) {
// Handle getTargetSession method: return underlying Session.
return this.target;
switch (method.getName()) {
case "equals":
// Only consider equal when proxies are identical.
return (proxy == args[0]);
case "hashCode":
// Use hashCode of Connection proxy.
return System.identityHashCode(proxy);
case "commit":
throw new TransactionInProgressException("Commit call not allowed within a managed transaction");
case "rollback":
throw new TransactionInProgressException("Rollback call not allowed within a managed transaction");
case "close":
// Handle close method: not to be closed within a transaction.
return null;
case "getTargetSession":
// Handle getTargetSession method: return underlying Session.
return this.target;
}
// Invoke method on target Session.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -1210,17 +1210,16 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Invocation on Session interface coming in...
if (method.getName().equals("equals")) {
// Only consider equal when proxies are identical.
return (proxy == args[0]);
}
else if (method.getName().equals("hashCode")) {
// Use hashCode of Session proxy.
return System.identityHashCode(proxy);
}
else if (method.getName().equals("close")) {
// Handle close method: suppress, not valid.
return null;
switch (method.getName()) {
case "equals":
// Only consider equal when proxies are identical.
return (proxy == args[0]);
case "hashCode":
// Use hashCode of Session proxy.
return System.identityHashCode(proxy);
case "close":
// Handle close method: suppress, not valid.
return null;
}
// Invoke method on target Session.

View File

@ -437,24 +437,23 @@ public class LocalSessionFactoryBuilder extends Configuration {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
if (method.getName().equals("equals")) {
switch (method.getName()) {
case "equals":
// Only consider equal when proxies are identical.
return (proxy == args[0]);
}
else if (method.getName().equals("hashCode")) {
case "hashCode":
// Use hashCode of EntityManagerFactory proxy.
return System.identityHashCode(proxy);
}
else if (method.getName().equals("getProperties")) {
case "getProperties":
return getProperties();
}
else if (method.getName().equals("getWrappedObject")) {
case "getWrappedObject":
// Call coming in through InfrastructureProxy interface...
return getSessionFactory();
}
// Regular delegation to the target SessionFactory,
// enforcing its full initialization...
}
// Regular delegation to the target SessionFactory,
// enforcing its full initialization...
try {
return method.invoke(getSessionFactory(), args);
}
catch (InvocationTargetException ex) {

View File

@ -708,16 +708,14 @@ public abstract class AbstractEntityManagerFactoryBean implements
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
if (method.getName().equals("equals")) {
switch (method.getName()) {
case "equals":
// Only consider equal when proxies are identical.
return (proxy == args[0]);
}
else if (method.getName().equals("hashCode")) {
case "hashCode":
// Use hashCode of EntityManagerFactory proxy.
return System.identityHashCode(proxy);
}
else if (method.getName().equals("unwrap")) {
case "unwrap":
// Handle JPA 2.1 unwrap method - could be a proxy match.
Class<?> targetClass = (Class<?>) args[0];
if (targetClass == null) {
@ -726,7 +724,10 @@ public abstract class AbstractEntityManagerFactoryBean implements
else if (targetClass.isInstance(proxy)) {
return proxy;
}
}
break;
}
try {
return this.entityManagerFactoryBean.invokeProxyMethod(method, args);
}
catch (InvocationTargetException ex) {

View File

@ -298,60 +298,58 @@ public abstract class ExtendedEntityManagerCreator {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Invocation on EntityManager interface coming in...
if (method.getName().equals("equals")) {
// Only consider equal when proxies are identical.
return (proxy == args[0]);
}
else if (method.getName().equals("hashCode")) {
// Use hashCode of EntityManager proxy.
return hashCode();
}
else if (method.getName().equals("getTargetEntityManager")) {
// Handle EntityManagerProxy interface.
return this.target;
}
else if (method.getName().equals("unwrap")) {
// Handle JPA 2.0 unwrap method - could be a proxy match.
Class<?> targetClass = (Class<?>) args[0];
if (targetClass == null) {
switch (method.getName()) {
case "equals":
// Only consider equal when proxies are identical.
return (proxy == args[0]);
case "hashCode":
// Use hashCode of EntityManager proxy.
return hashCode();
case "getTargetEntityManager":
// Handle EntityManagerProxy interface.
return this.target;
}
else if (targetClass.isInstance(proxy)) {
return proxy;
}
}
else if (method.getName().equals("isOpen")) {
if (this.containerManaged) {
return true;
}
}
else if (method.getName().equals("close")) {
if (this.containerManaged) {
throw new IllegalStateException("Invalid usage: Cannot close a container-managed EntityManager");
}
ExtendedEntityManagerSynchronization synch = (ExtendedEntityManagerSynchronization)
TransactionSynchronizationManager.getResource(this.target);
if (synch != null) {
// Local transaction joined - don't actually call close() before transaction completion
synch.closeOnCompletion = true;
case "unwrap":
// Handle JPA 2.0 unwrap method - could be a proxy match.
Class<?> targetClass = (Class<?>) args[0];
if (targetClass == null) {
return this.target;
}
else if (targetClass.isInstance(proxy)) {
return proxy;
}
break;
case "isOpen":
if (this.containerManaged) {
return true;
}
break;
case "close":
if (this.containerManaged) {
throw new IllegalStateException("Invalid usage: Cannot close a container-managed EntityManager");
}
ExtendedEntityManagerSynchronization synch = (ExtendedEntityManagerSynchronization)
TransactionSynchronizationManager.getResource(this.target);
if (synch != null) {
// Local transaction joined - don't actually call close() before transaction completion
synch.closeOnCompletion = true;
return null;
}
break;
case "getTransaction":
if (this.synchronizedWithTransaction) {
throw new IllegalStateException(
"Cannot obtain local EntityTransaction from a transaction-synchronized EntityManager");
}
break;
case "joinTransaction":
doJoinTransaction(true);
return null;
}
}
else if (method.getName().equals("getTransaction")) {
if (this.synchronizedWithTransaction) {
throw new IllegalStateException(
"Cannot obtain local EntityTransaction from a transaction-synchronized EntityManager");
}
}
else if (method.getName().equals("joinTransaction")) {
doJoinTransaction(true);
return null;
}
else if (method.getName().equals("isJoinedToTransaction")) {
// Handle JPA 2.1 isJoinedToTransaction method for the non-JTA case.
if (!this.jta) {
return TransactionSynchronizationManager.hasResource(this.target);
}
case "isJoinedToTransaction":
// Handle JPA 2.1 isJoinedToTransaction method for the non-JTA case.
if (!this.jta) {
return TransactionSynchronizationManager.hasResource(this.target);
}
break;
}
// Do automatic joining if required. Excludes toString, equals, hashCode calls.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -220,50 +220,45 @@ public abstract class SharedEntityManagerCreator {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Invocation on EntityManager interface coming in...
if (method.getName().equals("equals")) {
// Only consider equal when proxies are identical.
return (proxy == args[0]);
}
else if (method.getName().equals("hashCode")) {
// Use hashCode of EntityManager proxy.
return hashCode();
}
else if (method.getName().equals("toString")) {
// Deliver toString without touching a target EntityManager.
return "Shared EntityManager proxy for target factory [" + this.targetFactory + "]";
}
else if (method.getName().equals("getEntityManagerFactory")) {
// JPA 2.0: return EntityManagerFactory without creating an EntityManager.
return this.targetFactory;
}
else if (method.getName().equals("getCriteriaBuilder") || method.getName().equals("getMetamodel")) {
// JPA 2.0: return EntityManagerFactory's CriteriaBuilder/Metamodel (avoid creation of EntityManager)
try {
return EntityManagerFactory.class.getMethod(method.getName()).invoke(this.targetFactory);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
else if (method.getName().equals("unwrap")) {
// JPA 2.0: handle unwrap method - could be a proxy match.
Class<?> targetClass = (Class<?>) args[0];
if (targetClass != null && targetClass.isInstance(proxy)) {
return proxy;
}
}
else if (method.getName().equals("isOpen")) {
// Handle isOpen method: always return true.
return true;
}
else if (method.getName().equals("close")) {
// Handle close method: suppress, not valid.
return null;
}
else if (method.getName().equals("getTransaction")) {
throw new IllegalStateException(
"Not allowed to create transaction on shared EntityManager - " +
"use Spring transactions or EJB CMT instead");
switch (method.getName()) {
case "equals":
// Only consider equal when proxies are identical.
return (proxy == args[0]);
case "hashCode":
// Use hashCode of EntityManager proxy.
return hashCode();
case "toString":
// Deliver toString without touching a target EntityManager.
return "Shared EntityManager proxy for target factory [" + this.targetFactory + "]";
case "getEntityManagerFactory":
// JPA 2.0: return EntityManagerFactory without creating an EntityManager.
return this.targetFactory;
case "getCriteriaBuilder":
case "getMetamodel":
// JPA 2.0: return EntityManagerFactory's CriteriaBuilder/Metamodel (avoid creation of EntityManager)
try {
return EntityManagerFactory.class.getMethod(method.getName()).invoke(this.targetFactory);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
case "unwrap":
// JPA 2.0: handle unwrap method - could be a proxy match.
Class<?> targetClass = (Class<?>) args[0];
if (targetClass != null && targetClass.isInstance(proxy)) {
return proxy;
}
break;
case "isOpen":
// Handle isOpen method: always return true.
return true;
case "close":
// Handle close method: suppress, not valid.
return null;
case "getTransaction":
throw new IllegalStateException(
"Not allowed to create transaction on shared EntityManager - " +
"use Spring transactions or EJB CMT instead");
}
// Determine current EntityManager: either the transactional one
@ -271,25 +266,27 @@ public abstract class SharedEntityManagerCreator {
EntityManager target = EntityManagerFactoryUtils.doGetTransactionalEntityManager(
this.targetFactory, this.properties, this.synchronizedWithTransaction);
if (method.getName().equals("getTargetEntityManager")) {
// Handle EntityManagerProxy interface.
if (target == null) {
throw new IllegalStateException("No transactional EntityManager available");
}
return target;
switch (method.getName()) {
case "getTargetEntityManager":
// Handle EntityManagerProxy interface.
if (target == null) {
throw new IllegalStateException("No transactional EntityManager available");
}
return target;
case "unwrap":
Class<?> targetClass = (Class<?>) args[0];
if (targetClass == null) {
return (target != null ? target : proxy);
}
// We need a transactional target now.
if (target == null) {
throw new IllegalStateException("No transactional EntityManager available");
}
// Still perform unwrap call on target EntityManager.
break;
}
else if (method.getName().equals("unwrap")) {
Class<?> targetClass = (Class<?>) args[0];
if (targetClass == null) {
return (target != null ? target : proxy);
}
// We need a transactional target now.
if (target == null) {
throw new IllegalStateException("No transactional EntityManager available");
}
// Still perform unwrap call on target EntityManager.
}
else if (transactionRequiringMethods.contains(method.getName())) {
if (transactionRequiringMethods.contains(method.getName())) {
// We need a transactional target now, according to the JPA spec.
// Otherwise, the operation would get accepted but remain unflushed...
if (target == null || (!TransactionSynchronizationManager.isActualTransactionActive() &&
@ -372,36 +369,36 @@ public abstract class SharedEntityManagerCreator {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Invocation on Query interface coming in...
if (method.getName().equals("equals")) {
// Only consider equal when proxies are identical.
return (proxy == args[0]);
}
else if (method.getName().equals("hashCode")) {
// Use hashCode of EntityManager proxy.
return hashCode();
}
else if (method.getName().equals("unwrap")) {
// Handle JPA 2.0 unwrap method - could be a proxy match.
Class<?> targetClass = (Class<?>) args[0];
if (targetClass == null) {
return this.target;
}
else if (targetClass.isInstance(proxy)) {
return proxy;
}
}
else if (method.getName().equals("getOutputParameterValue")) {
if (this.entityManager == null) {
Object key = args[0];
if (this.outputParameters == null || !this.outputParameters.containsKey(key)) {
throw new IllegalArgumentException("OUT/INOUT parameter not available: " + key);
switch (method.getName()) {
case "equals":
// Only consider equal when proxies are identical.
return (proxy == args[0]);
case "hashCode":
// Use hashCode of EntityManager proxy.
return hashCode();
case "unwrap":
// Handle JPA 2.0 unwrap method - could be a proxy match.
Class<?> targetClass = (Class<?>) args[0];
if (targetClass == null) {
return this.target;
}
Object value = this.outputParameters.get(key);
if (value instanceof IllegalArgumentException) {
throw (IllegalArgumentException) value;
else if (targetClass.isInstance(proxy)) {
return proxy;
}
return value;
}
break;
case "getOutputParameterValue":
if (this.entityManager == null) {
Object key = args[0];
if (this.outputParameters == null || !this.outputParameters.containsKey(key)) {
throw new IllegalArgumentException("OUT/INOUT parameter not available: " + key);
}
Object value = this.outputParameters.get(key);
if (value instanceof IllegalArgumentException) {
throw (IllegalArgumentException) value;
}
return value;
}
break;
}
// Invoke method on actual Query object.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -237,18 +237,18 @@ public class SingleConnectionFactory extends DelegatingConnectionFactory impleme
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("equals")) {
// Only consider equal when proxies are identical.
return (proxy == args[0]);
}
else if (method.getName().equals("hashCode")) {
// Use hashCode of Connection proxy.
return System.identityHashCode(proxy);
}
else if (method.getName().equals("close")) {
// Handle close method: don't pass the call on.
return null;
switch (method.getName()) {
case "equals":
// Only consider equal when proxies are identical.
return (proxy == args[0]);
case "hashCode":
// Use hashCode of Connection proxy.
return System.identityHashCode(proxy);
case "close":
// Handle close method: don't pass the call on.
return null;
}
try {
return method.invoke(this.target, args);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -136,24 +136,23 @@ public class TransactionAwareConnectionFactoryProxy extends DelegatingConnection
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Invocation on Connection interface coming in...
if (method.getName().equals("equals")) {
// Only consider equal when proxies are identical.
return (proxy == args[0]);
}
else if (method.getName().equals("hashCode")) {
// Use hashCode of Connection proxy.
return System.identityHashCode(proxy);
}
else if (method.getName().equals("getLocalTransaction")) {
if (ConnectionFactoryUtils.isConnectionTransactional(this.target, this.connectionFactory)) {
throw new javax.resource.spi.IllegalStateException(
"Local transaction handling not allowed within a managed transaction");
}
}
else if (method.getName().equals("close")) {
// Handle close method: only close if not within a transaction.
ConnectionFactoryUtils.doReleaseConnection(this.target, this.connectionFactory);
return null;
switch (method.getName()) {
case "equals":
// Only consider equal when proxies are identical.
return (proxy == args[0]);
case "hashCode":
// Use hashCode of Connection proxy.
return System.identityHashCode(proxy);
case "getLocalTransaction":
if (ConnectionFactoryUtils.isConnectionTransactional(this.target, this.connectionFactory)) {
throw new javax.resource.spi.IllegalStateException(
"Local transaction handling not allowed within a managed transaction");
}
return this.target.getLocalTransaction();
case "close":
// Handle close method: only close if not within a transaction.
ConnectionFactoryUtils.doReleaseConnection(this.target, this.connectionFactory);
return null;
}
// Invoke method on target Connection.

View File

@ -719,16 +719,12 @@ public class MvcUriComponentsBuilder {
@Override
@Nullable
public Object intercept(Object obj, Method method, Object[] args, @Nullable MethodProxy proxy) {
if (method.getName().equals("getControllerType")) {
return this.controllerType;
switch (method.getName()) {
case "getControllerType": return this.controllerType;
case "getControllerMethod": return this.controllerMethod;
case "getArgumentValues": return this.argumentValues;
}
else if (method.getName().equals("getControllerMethod")) {
return this.controllerMethod;
}
else if (method.getName().equals("getArgumentValues")) {
return this.argumentValues;
}
else if (ReflectionUtils.isObjectMethod(method)) {
if (ReflectionUtils.isObjectMethod(method)) {
return ReflectionUtils.invokeMethod(method, obj, args);
}
else {