IntroduçãoNa primeira quinzena do mês de junho (2006), respondi a uma questão sobre performance em instaciamentos de componentes (CFC), e a possibilidade de acelerar a criação de um objeto do tipo componente. Pré-requisitoColdFusion MX 7.0.1, e conhecimentos sobre Application.cfc (livedocs). ObjetivoObservar alguns métodos não documentados em alguns escopos. ConceitosVeremos então os scripts que enviei como resposta a questão, descrita no início, e em seguida os resultados da pesquisa baseada nas propriedades dos escopos. ConteúdoCódigo enviado por mim como resposta, formado por três arquivos bem simples, apenas para demonstração, onde encontramos o arquivo Application.cfc que foi estendido do arquivo testeObjetos.cfc e instanciado no arquivo testeObjetos.cfm. Esta estrutura foi necessária para descartar o uso do createobject, com parâmetro component, para instanciar o componente testeObjetos.cfc, e estimulando a utilização do escopo request e do evento/método onRequestStart, para criar uma variável que contivesse os atributos e métodos do objeto testeObjetos testeObjetos.cfc <cfcomponent output=”no”> Application.cfc <cfcomponent extends=”testeObjetos”> testeObjetos.cfc <h1>O Application.cfc cria o objeto sempre</h1> Conhecendo maisPorém esta solução geraria uma variável para cada requisição, e algumas delas não utilizariam esta variável, foi então que as surpresas (não documentadas) começaram. Para os testes reescrevi o Application.cfc, e utilizei o mesmo componente testeObjetos.cfc. Application.cfc <cfcomponent extends=”testeObjetos”> Primeiro no escopo application, onde pude acessar os métodos do application.cfc de duas formas. Através do método testeObjetos2.cfm <cfdump var=”#application.getEventInvoker()#”> table.cfdump_wddx, table.cfdump_xml, table.cfdump_struct, table.cfdump_array, table.cfdump_query, table.cfdump_cfc, table.cfdump_object, table.cfdump_binary, table.cfdump_udf, table.cfdump_udfbody, table.cfdump_udfarguments { font-size: xx-small; font-family: verdana, arial, helvetica, sans-serif; cell-spacing: 2px; } table.cfdump_wddx th, table.cfdump_xml th, table.cfdump_struct th, table.cfdump_array th, table.cfdump_query th, table.cfdump_cfc th, table.cfdump_object th, table.cfdump_binary th, table.cfdump_udf th, table.cfdump_udfbody th, table.cfdump_udfarguments th { text-align: left; color: white; padding: 5px; } table.cfdump_wddx td, table.cfdump_xml td, table.cfdump_struct td, table.cfdump_array td, table.cfdump_query td, table.cfdump_cfc td, table.cfdump_object td, table.cfdump_binary td, table.cfdump_udf td, table.cfdump_udfbody td, table.cfdump_udfarguments td { padding: 3px; background-color: #ffffff; vertical-align : top; } table.cfdump_wddx { background-color: #000000; } table.cfdump_wddx th.wddx { background-color: #444444; } table.cfdump_xml { background-color: #888888; } table.cfdump_xml th.xml { background-color: #aaaaaa; } table.cfdump_xml td.xml { background-color: #dddddd; } table.cfdump_struct { background-color: #0000cc ; } table.cfdump_struct th.struct { background-color: #4444cc ; } table.cfdump_struct td.struct { background-color: #ccddff; } table.cfdump_array { background-color: #006600 ; } table.cfdump_array th.array { background-color: #009900 ; } table.cfdump_array td.array { background-color: #ccffcc ; } table.cfdump_query { background-color: #884488 ; } table.cfdump_query th.query { background-color: #aa66aa ; } table.cfdump_query td.query { background-color: #ffddff ; } table.cfdump_cfc { background-color: #ff0000; } table.cfdump_cfc th.cfc{ background-color: #ff4444; } table.cfdump_cfc td.cfc { background-color: #ffcccc; } table.cfdump_object { background-color : #ff0000; } table.cfdump_object th.object{ background-color: #ff4444; } table.cfdump_binary { background-color : #eebb00; } table.cfdump_binary th.binary { background-color: #ffcc44; } table.cfdump_binary td { font-size: x-small; } table.cfdump_udf { background-color: #aa4400; } table.cfdump_udf th.udf { background-color: #cc6600; } table.cfdump_udfarguments { background-color: #dddddd; cell-spacing: 3; } table.cfdump_udfarguments th { background-color: #eeeeee; color: #000000; } function dump ( obj ) { var out = \’\’ ; if ( typeof obj == “object” ) { for ( key in obj ) { if ( typeof obj[key] != “function” ) out += key + \’: \’ + obj[key] + \’ function cfdump_toggleRow(source) { //target is the right cell if(document.all) target = source.parentElement.cells[1]; else target = source.parentNode.lastChild ; cfdump_toggleTarget( target, cfdump_toggleSource( source ) ) ; } function cfdump_toggleXmlDoc(source) { var caption = source.innerHTML.split( \’ [\' ) ; // toggle source (header) if ( source.style.fontStyle == \'italic\' ) { // closed -> short source.style.fontStyle = \'normal\' ; source.innerHTML = caption[0] + \’ [short version]\’ ; source.title = \’click to maximize\’ ; switchLongToState = \’closed\’ ; switchShortToState = \’open\’ ; } else if ( source.innerHTML.indexOf(\’[short version]\’) != -1 ) { // short -> full source.innerHTML = caption[0] + \’ [long version]\’ ; source.title = \’click to collapse\’ ; switchLongToState = \’open\’ ; switchShortToState = \’closed\’ ; } else { // full -> closed source.style.fontStyle = \’italic\’ ; source.title = \’click to expand\’ ; source.innerHTML = caption[0] ; switchLongToState = \’closed\’ ; switchShortToState = \’closed\’ ; } // Toggle the target (everething below the header row). // First two rows are XMLComment and XMLRoot – they are part // of the long dump, the rest are direct children – part of the // short dump if(document.all) { var table = source.parentElement.parentElement ; for ( var i = 1; i < table.rows.length; i++ ) { target = table.rows[i] ; if ( i < 3 ) cfdump_toggleTarget( target, switchLongToState ) ; else cfdump_toggleTarget( target, switchShortToState ) ; } } else { var table = source.parentNode.parentNode ; var row = 1; for ( var i = 1; i < table.childNodes.length; i++ ) { target = table.childNodes[i] ; if( target.style ) { if ( row < 3 ) { cfdump_toggleTarget( target, switchLongToState ) ; } else { cfdump_toggleTarget( target, switchShortToState ) ; } row++; } } } } function cfdump_toggleTable(source) { var switchToState = cfdump_toggleSource( source ) ; if(document.all) { var table = source.parentElement.parentElement ; for ( var i = 1; i < table.rows.length; i++ ) { target = table.rows[i] ; cfdump_toggleTarget( target, switchToState ) ; } } else { var table = source.parentNode.parentNode ; for ( var i = 1; i < table.childNodes.length; i++ ) { target = table.childNodes[i] ; if(target.style) { cfdump_toggleTarget( target, switchToState ) ; } } } } function cfdump_toggleSource ( source ) { if ( source.style.fontStyle == \’italic\’ || source.style.fontStyle == null) { source.style.fontStyle = \’normal\’ ; source.title = \’click to collapse\’ ; return \’open\’ ; } else { source.style.fontStyle = \’italic\’ ; source.title = \’click to expand\’ ; return \’closed\’ ; } } function cfdump_toggleTarget ( target, switchToState ) { if ( switchToState == \’open\’ ) target.style.display = \’\’ ; else target.style.display = \’none\’ ; }
Onde encontrei getThisScope() testeObjetos3.cfm <cfdump var=”#application.getEventInvoker().getThisScope()#”>
Encontrei também getApplicationSettings(), que retornará o mesmo valor contido em getEventInvoker().getThisScope(). testeObjetos4.cfm <cfdump var=”#application.getApplicationSettings()#”> Com isso podemos acessar os métodos diretamente, mas transforma o escopo this, deixando o objeto como um saco de funções. testeObjetos5.cfm <cfset obj = application.getEventInvoker().getThisScope().testeObjetos(1) >
Uma outra forma seria utilizar o método invoke(), que acabaria sendo o mesmo que utilizar o createobject, é preciso ter cuidado na utilização deste método, veja porque. testeObjetos6.cfm <cfset obj = application.getEventInvoker().invoke(‘testeObjetos’,listtoarray(‘1′))>
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| struct | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| TESTEOBJETOS |
|
|||||||||||||||||||||
| struct | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ID | 1 | |||||||||||||||||||||
| TESTEOBJETOS |
|
|||||||||||||||||||||
E seguindo com as surpresas, um outro achado foi na udf.
testeObjetos7.cfm
<cfset funcao = structnew() >
<cfset funcao.funcao = application.getApplicationSettings().testeObjetos >
<cfset funcao.metadata = funcao.funcao.getMetaData() >
<cfset funcao.path = funcao.funcao.getPagePath() >
<cfset funcao.SuperScope = funcao.funcao.getSuperScope() >
<cfdump var=”#funcao#”>
| struct | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| FUNCAO |
|
|||||||||||||||||||||
| METADATA |
|
|||||||||||||||||||||
| PATH | C:\Arquivos de programas\Apache Software Foundation\Tomcat 5.0\webapps\cfusion\testeObjetos.cfc | |||||||||||||||||||||
| SUPERSCOPE |
|
|||||||||||||||||||||
Sem esquecer da função GetPageContext
testeObjetos8.cfm
<cfoutput>#GetPageContext().getFusionContext().getPagePath()#</cfoutput>
C:\Arquivos de programas\Apache Software Foundation\Tomcat 5.0\webapps\cfusion\testeEscopo.cfm
E ainda uma série de informações sobre a aplicação
testeObjetos9.cfm
<!— <cfapplication loginstorage=session > —>
<cfset application.setStoreloginCredentialInSession(‘YES’) > loginstorage está em session ? <cfoutput>#application.getStoreloginCredentialInSession()#</cfoutput>
applicationname = <cfoutput>#application.getName()#</cfoutput>
tempo de vida da aplicação = <cfoutput>#application.getElapsedTime()#</cfoutput>
último acesso = <cfoutput>#application.getTimeSinceLastAccess()#</cfoutput>
intervalo máximo de inatividade permitido = <cfoutput>#application.getMaxInactiveInterval()#</cfoutput>
<cfoutput>#application.getNames().next()#</cfoutput>
a aplicação expirou? <cfoutput>#application.expired()#</cfoutput>
é o primeiro acesso da aplicação? <cfoutput>#application.isNew()#</cfoutput>
aplicação foi iniciada? <cfoutput>#application.isInited()#</cfoutput>
<!—
<cfset application.setLastAccess()>
<cfset application.SetMaxInactiveInterval(0) >
<cfset application.cleanup() >
<cfset application.setIsInited(false) >
—>
Então a curiosidade aumentou, e na sessão o que poderia ser encontrado ?
testeObjetos10.cfm
<cfoutput>#session.IsJ2eeSession()#</cfoutput> <cfoutput>#session.getAppName()#</cfoutput>
<cfoutput>#session.getNames().next()#</cfoutput>
<cfoutput>#session.getElapsedTime()#</cfoutput>
<cfoutput>#session.getTimeSinceLastAccess()#</cfoutput>
<cfoutput>#session.getMaxInactiveInterval()#</cfoutput>
<cfoutput>#session.expired()#</cfoutput>
<cfoutput>#session.isNew()#</cfoutput>
E para terminar os testes.
testeObjetos11.cfm
<!— aplicável a struct e escopos —>
<cfset form.vazio = “”>
<cfset form.clear() >
<cfset form.key1 = “valor original”>
<cfset form.key2 = “”>
<cfset form.put(“key1″,”put retorna valor anterior”) >
<cfset form.key1old = form.put(“key1″,”put 2 “) >
<cfset form.acessando = form.get(‘key1′)>
<cfset form.Empty = form.isEmpty()>
<cfset form.struct = form.clone()>
<cfset form.remove(‘key2′) >
<cfset form.numItens = form.size()+1>
<cfdump var=”#form#”><br /> <!— aplicável apenas a array —>
<cfset array = listtoarray(‘valor será eliminado’) >
<cfset array.clear() >
<cfset arrayappend(array , “size = “&array.size() ) >
<cfset arrayappend(array , “getDimension = “&array.getDimension() ) >
<cfset arrayappend(array , “dimensionOf = “&array.dimensionOf(array) ) >
<cfset arrayappend(array , “isEmpty = “&array.isEmpty() ) >
<cfset arrayappend(array , “4″ ) >
<cfset arrayappend(array , array.get(0) ) >
<cfset arrayappend(array , array.clone() ) >
<cfset array.remove(4) >
<cfdump var=”#array#”>
| struct | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| ACESSANDO | put 2 | ||||||||||
| EMPTY | NO | ||||||||||
| KEY1 | put 2 | ||||||||||
| KEY1OLD | put retorna valor anterior | ||||||||||
| NUMITENS | 6 | ||||||||||
| STRUCT |
|
||||||||||
| array | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | size = 0 | ||||||||||||||
| 2 | getDimension = 1 | ||||||||||||||
| 3 | dimensionOf = 1 | ||||||||||||||
| 4 | isEmpty = NO | ||||||||||||||
| 5 | size = 0 | ||||||||||||||
| 6 |
|
||||||||||||||
Conclusão
Os testes valeram apenas pelas agradáveis surpresas, porque o código que tornaria mais rápida a criação de objetos do tipo componente, é o que utilizei como resposta no mês de passado, com os arquivos Application.cfc, testeObjetos.cfc e testeObjeto.cfm. Apesar desta forma não estar presente em nenhuma framework, e muito menos documentada, assim como os métodos que demonstrei.
–
Pedro Claudio – pcsilva@mxstudio.com.br
visite o fórum MXStudio ColdFusion
FormatCF(new Array(\’testeObjetos.cfc\’,\’Application.cfc\’,\’testeObjetos.cfm\’,\’Application.cfc2\’,\’testeObjetos2.cfm\’,\’testeObjetos3.cfm\’,\’testeObjetos4.cfm\’,\’testeObjetos5.cfm\’,\’testeObjetos6.cfm\’,\’testeObjetos7.cfm\’,\’testeObjetos8.cfm\’,\’testeObjetos9.cfm\’,\’testeObjetos10.cfm\’,\’testeObjetos11.cfm\’));




ShareThis