From e955e52f2f108517535d4c0541cc5b8bd5e6c22b Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Fri, 29 May 2020 23:07:25 +0200 Subject: [PATCH] Refactor method name dispatching to switch statements Closes gh-25163 --- .../core/SerializableTypeWrapper.java | 33 ++- .../jdbc/core/JdbcTemplate.java | 47 ++-- .../LazyConnectionDataSourceProxy.java | 161 +++++++------- .../SingleConnectionDataSource.java | 47 ++-- .../TransactionAwareDataSourceProxy.java | 73 +++---- .../connection/SingleConnectionFactory.java | 203 +++++++++--------- ...ransactionAwareConnectionFactoryProxy.java | 57 +++-- .../orm/hibernate5/HibernateTemplate.java | 23 +- .../LocalSessionFactoryBuilder.java | 21 +- .../jpa/AbstractEntityManagerFactoryBean.java | 15 +- .../orm/jpa/ExtendedEntityManagerCreator.java | 102 +++++---- .../orm/jpa/SharedEntityManagerCreator.java | 179 ++++++++------- .../connection/SingleConnectionFactory.java | 24 +-- ...ransactionAwareConnectionFactoryProxy.java | 37 ++-- .../annotation/MvcUriComponentsBuilder.java | 14 +- 15 files changed, 494 insertions(+), 542 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/core/SerializableTypeWrapper.java b/spring-core/src/main/java/org/springframework/core/SerializableTypeWrapper.java index 04ef40d528b..b241f0cfc74 100644 --- a/spring-core/src/main/java/org/springframework/core/SerializableTypeWrapper.java +++ b/spring-core/src/main/java/org/springframework/core/SerializableTypeWrapper.java @@ -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)); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java index 313f450be2d..c7a83d1a12a 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java @@ -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. diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/LazyConnectionDataSourceProxy.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/LazyConnectionDataSourceProxy.java index 897ebbcbc86..e22d47de372 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/LazyConnectionDataSourceProxy.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/LazyConnectionDataSourceProxy.java @@ -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"); + } } } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/SingleConnectionDataSource.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/SingleConnectionDataSource.java index 42d8f9c2810..f61b3e7b666 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/SingleConnectionDataSource.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/SingleConnectionDataSource.java @@ -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. diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/TransactionAwareDataSourceProxy.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/TransactionAwareDataSourceProxy.java index 6a502d9496a..f1afd5604c0 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/TransactionAwareDataSourceProxy.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/TransactionAwareDataSourceProxy.java @@ -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) { diff --git a/spring-jms/src/main/java/org/springframework/jms/connection/SingleConnectionFactory.java b/spring-jms/src/main/java/org/springframework/jms/connection/SingleConnectionFactory.java index 84b2378ab05..1a463c3b4fe 100644 --- a/spring-jms/src/main/java/org/springframework/jms/connection/SingleConnectionFactory.java +++ b/spring-jms/src/main/java/org/springframework/jms/connection/SingleConnectionFactory.java @@ -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; - } - return null; + 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; } - 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."); + if (other == null || !Proxy.isProxyClass(other.getClass())) { + return false; } - } - } - else if (method.getName().equals("getExceptionListener")) { - synchronized (connectionMonitor) { - if (this.localExceptionListener != null) { - return this.localExceptionListener; + 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 { - return getExceptionListener(); + 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("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]; + case "getExceptionListener": + synchronized (connectionMonitor) { + if (this.localExceptionListener != null) { + return this.localExceptionListener; + } + else { + return getExceptionListener(); + } } - 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); + 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; + } } - } - 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(); + 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]; } - catch (Throwable ex) { - logger.trace("Failed to close newly obtained JMS Session", ex); + 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); } - throw new javax.jms.IllegalStateException(msg); } - return session; - } + 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); } diff --git a/spring-jms/src/main/java/org/springframework/jms/connection/TransactionAwareConnectionFactoryProxy.java b/spring-jms/src/main/java/org/springframework/jms/connection/TransactionAwareConnectionFactoryProxy.java index def15e2b4f4..3dbbfb5c732 100644 --- a/spring-jms/src/main/java/org/springframework/jms/connection/TransactionAwareConnectionFactoryProxy.java +++ b/spring-jms/src/main/java/org/springframework/jms/connection/TransactionAwareConnectionFactoryProxy.java @@ -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. diff --git a/spring-orm/src/main/java/org/springframework/orm/hibernate5/HibernateTemplate.java b/spring-orm/src/main/java/org/springframework/orm/hibernate5/HibernateTemplate.java index 685dc3406de..b025de49003 100644 --- a/spring-orm/src/main/java/org/springframework/orm/hibernate5/HibernateTemplate.java +++ b/spring-orm/src/main/java/org/springframework/orm/hibernate5/HibernateTemplate.java @@ -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. diff --git a/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBuilder.java b/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBuilder.java index e6f50a90d62..7d07b5c1177 100644 --- a/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBuilder.java +++ b/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBuilder.java @@ -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) { diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/AbstractEntityManagerFactoryBean.java b/spring-orm/src/main/java/org/springframework/orm/jpa/AbstractEntityManagerFactoryBean.java index b5d521bc896..f417b4d47af 100644 --- a/spring-orm/src/main/java/org/springframework/orm/jpa/AbstractEntityManagerFactoryBean.java +++ b/spring-orm/src/main/java/org/springframework/orm/jpa/AbstractEntityManagerFactoryBean.java @@ -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) { diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/ExtendedEntityManagerCreator.java b/spring-orm/src/main/java/org/springframework/orm/jpa/ExtendedEntityManagerCreator.java index bfdc08711aa..c61157ef6ee 100644 --- a/spring-orm/src/main/java/org/springframework/orm/jpa/ExtendedEntityManagerCreator.java +++ b/spring-orm/src/main/java/org/springframework/orm/jpa/ExtendedEntityManagerCreator.java @@ -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. diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/SharedEntityManagerCreator.java b/spring-orm/src/main/java/org/springframework/orm/jpa/SharedEntityManagerCreator.java index c1e77af3216..5b109cf8986 100644 --- a/spring-orm/src/main/java/org/springframework/orm/jpa/SharedEntityManagerCreator.java +++ b/spring-orm/src/main/java/org/springframework/orm/jpa/SharedEntityManagerCreator.java @@ -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; - } - 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. + 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 (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. diff --git a/spring-tx/src/main/java/org/springframework/jca/cci/connection/SingleConnectionFactory.java b/spring-tx/src/main/java/org/springframework/jca/cci/connection/SingleConnectionFactory.java index 937f0cb509d..94561b3b32a 100644 --- a/spring-tx/src/main/java/org/springframework/jca/cci/connection/SingleConnectionFactory.java +++ b/spring-tx/src/main/java/org/springframework/jca/cci/connection/SingleConnectionFactory.java @@ -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); } diff --git a/spring-tx/src/main/java/org/springframework/jca/cci/connection/TransactionAwareConnectionFactoryProxy.java b/spring-tx/src/main/java/org/springframework/jca/cci/connection/TransactionAwareConnectionFactoryProxy.java index 9e9c09f8306..51f03f4a36d 100644 --- a/spring-tx/src/main/java/org/springframework/jca/cci/connection/TransactionAwareConnectionFactoryProxy.java +++ b/spring-tx/src/main/java/org/springframework/jca/cci/connection/TransactionAwareConnectionFactoryProxy.java @@ -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. diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.java index 765823866b8..d865db0709e 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.java @@ -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 {