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-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.