2012-08-16 9 views
13

Estoy tratando de usar un SocketImpl personalizado con SSL en Java. Por eso necesito configurar el socket factory de ServerSocket. Ahora me doy cuenta de que es estático, lo que me crea problemas ya que quiero proporcionarle algunos parámetros que difieren entre cada instancia ServerSocket. ¿Alguien sabe la razón detrás de hacerlo estático? Para mí, se siente como una restricción innecesaria que solo introduce más estado global en tu aplicación.¿Por qué ServerSocket.setSocketFactory estática?

Actualización Parece haber alguna confusión sobre por qué esto es una molestia. El problema que esto crea es que me obliga a usar la misma fábrica en toda la aplicación. ¿Qué sucede si quiero usar el SocketImpl predeterminado en un lugar y uno personalizado en otro? Eso no se puede hacer sin recurrir a algunos feos trucos de reflexión, porque la fábrica no se puede cambiar una vez que se ha establecido. Tampoco puedo hacer que mi fábrica cree la implementación predeterminada porque SocksSocketImpl es un paquete privado.

+2

¿La pregunta que desea responder es "por qué está estática"? No es una pregunta más práctica "¿cómo puedo resolver este problema"? –

+0

¿por qué no puedes asignar esos parámetros a algunas variables dentro de tu clase SocketImplFactory? ¿Por qué necesita anular una función estática, por imposible que pueda ser? –

+0

¿Dónde digo que quiero anular una función estática? – Yrlec

Respuesta

4

SocketImpl es una clase abstracta que proporciona una interfaz para implementaciones de socket de personalización. Las subclases de SocketImpl no son con la intención de crear una instancia explícita. En cambio, son creados por SocketImplFactory. La motivación para este diseño es permitirle cambiar el tipo predeterminado de socket utilizado por una aplicación completa por llamando a Socket.setSocketImplFactory(), por lo que es innecesario reescribir todo su código de red. Los sockets personalizados son necesarios para las características tales como SSL y firewall tunneling. Desafortunadamente, la naturaleza global de de setSocketImplFactory() es bastante limitado, ya que no le permite usar múltiples tipos de sockets dentro de una única aplicación . Puede solucionarlo subclasando Socket y utilizando el constructor SocketImpl protegido que se introdujo en JDK 1.1.

Referencia: http://www.devx.com/tips/Tip/26363

+2

Si observa el código fuente de ServerSocket, puede ver que esto no es suficiente. Si miras en implAccept (Socket s) puedes ver que obtiene su instancia de SocketImpl llamando a getImpl() -> createImpl() -> setImpl(). En setImpl() utiliza el campo de fábrica estático si es! = Nulo; de lo contrario, llama a los nuevos SocksSocketImpl(). En otras palabras: si quieres un SocketImpl personalizado, debes configurarlo de fábrica. De lo contrario, no puedes llamar a implAccept(). – Yrlec

+1

También debería agregar que el constructor ServerSocket (SocketImpl impl) es un paquete privado, por lo que no puedo usarlo. – Yrlec

1

Para mí parece que tener este setter estático lo hace más fácil de usar, porque no es necesario tener una instancia de ServerSocket y le permite configurar la fábrica de Socket sin tener que hacer referencia a ella. Creo que hacer que setter global sea realmente más fácil de implementar, ¿por qué es complicado para ti?

1

Mira el Constructor of ServerSocket

Si la aplicación ha especificado una fábrica de sockets de servidor, el método createSocketImpl de que la fábrica está llamado a crear la aplicación toma real. De lo contrario, se crea un socket "simple".

Por lo tanto, tiene que ser estático, porque existe la necesidad de configurar la fábrica si desea que se use cuando está creando una nueva instancia de un zócalo.

+0

Eso solo lleva a la pregunta de seguimiento, ¿por qué es createSocketImpl llamado en el constructor? Hay un constructor que le permite especificar la instancia de SocketImpl manualmente (ServerSocket (SocketImpl impl)) pero es un paquete privado. – Yrlec

0

se puede esperar una fábrica no estático para saber cómo crear una instancia de la clase personalizada mágicamente?

+0

Espero poder suministrarle mi propia fábrica no estática. ¿Por qué la instancia de fábrica debe almacenarse en un campo estático? – Yrlec

0

Esto me parece un caso clásico de Factory Pattern, en el cual se proporciona un objeto de fábrica personalizado con configuraciones que dictan cómo se crean las instancias de una determinada clase. Tiene mucho sentido que los métodos que manipulan las fábricas sean estáticos, ya que la fábrica actúa como un "metaobjeto", que dirige la creación de otros objetos.

Tener una fábrica de cada instancia simplemente no tendría sentido desde el punto de vista del diseño. ¿Cuál sería el sentido de tener una fábrica diferente por instancia? ¿Planea crear instancias de ServerSocket desde otras instancias? Si desea configuraciones diferentes, solo tendrá que suministrar una fábrica diferente cada vez.

+0

Mi aplicación necesita diferentes ServerSockets para diferentes partes de la aplicación. Una parte necesita un zócalo TCP normal y una parte necesita zócalos PseudoTCP de Ice4j. Lo que hace que esto sea aún más extraño es que no puedo cambiar la fábrica una vez que se ha configurado. setFactory arroja una excepción para cada llamada subsiguiente. – Yrlec

+1

@Yrlec: lo que necesita entonces es un patrón de decorador, que permite la personalización de instancias individuales. Pero las fábricas son siempre estáticas por definición. – Tudor

+0

Bueno, no soy uno que haya decidido el patrón de ServerSocket. Solo creo que es una limitación muy extraña. – Yrlec

1

Es bastante desagradable, pero podría crear un DelegatingSocketFactory que busque una copia de seguridad de la pila de llamadas a quién lo llamó y cree un SocksSocketImpl (utilizando el reflejo para ordenar la accesibilidad) o utilice el Ice4J. ¡Esto cuenta como un truco de reflexión!

Cuestiones relacionadas