这里举一个例子,是spring boot的,JFinal是一个道理和一样的解决办法。
1:Spring Boot的事物增强。
先看代码:
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import javax.swing.*;
@SpringBootApplication
public class DemoApplication {
public DemoApplication() {
System.out.println("im constructor");
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new DemoApplication();
createAndShowGUI();
}
});
SpringApplication.run(DemoApplication.class, args);
}
private static void createAndShowGUI() {
System.out.println("im static");
}
}
执行结果:
im constructor
im static
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.6.RELEASE)
2019-08-04 14:29:55.249 INFO 1160 --- [ main] com.example.demo.DemoApplication : Starting DemoApplication on PC-20170518JWLD with PID 1160 (C:\Users\Administrator\Desktop\demo\target\classes started by Administrator in C:\Users\Administrator\Desktop\demo)
2019-08-04 14:29:55.254 INFO 1160 --- [ main] com.example.demo.DemoApplication : No active profile set, falling back to default profiles: default
im constructor
2019-08-04 14:29:56.374 INFO 1160 --- [ main] com.example.demo.DemoApplication : Started DemoApplication in 1.798 seconds (JVM running for 2.683)
分析:可以看到构造方法被执行了两次,但是静态方法是正常的只被执行了一次。在来看下是谁调用了两次构造方法。
添加打印方法。为了避免报错引起程序中断加上try catch。再次执行。
public DemoApplication() {
try{
Thread.dumpStack();//打印调用栈
}catch (Exception e){
}
System.out.println("im constructor");
}
输出:
java.lang.Exception: Stack trace
at java.lang.Thread.dumpStack(Thread.java:1336)
at com.example.demo.DemoApplication.<init>(DemoApplication.java:13)
at com.example.demo.DemoApplication$1.run(DemoApplication.java:25)
at java.awt.event.InvocationEvent.dispatch$$$capture(InvocationEvent.java:311)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:205)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
im constructor
im static
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.6.RELEASE)
2019-08-04 14:36:24.443 INFO 9152 --- [ main] com.example.demo.DemoApplication : Starting DemoApplication on PC-20170518JWLD with PID 9152 (C:\Users\Administrator\Desktop\demo\target\classes started by Administrator in C:\Users\Administrator\Desktop\demo)
2019-08-04 14:36:24.452 INFO 9152 --- [ main] com.example.demo.DemoApplication : No active profile set, falling back to default profiles: default
java.lang.Exception: Stack trace
at java.lang.Thread.dumpStack(Thread.java:1336)
at com.example.demo.DemoApplication.<init>(DemoApplication.java:13)
at com.example.demo.DemoApplication$$EnhancerBySpringCGLIB$$88aee20c.<init>(<generated>)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:172)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:87)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1295)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1197)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:845)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:877)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:742)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:389)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:311)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1213)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1202)
at com.example.demo.DemoApplication.main(DemoApplication.java:30)im constructor
2019-08-04 14:36:25.599 INFO 9152 --- [ main] com.example.demo.DemoApplication : Started DemoApplication in 2.063 seconds (JVM running for 3.578)
Disconnected from the target VM, address: '127.0.0.1:53365', transport: 'socket'
可以看到是
new DemoApplication();
SpringApplication.run(DemoApplication.class, args);
这两个方法的调用。先来说解决办法再说引起的原因。
先说第一个解决办法:既然知道构造方法被执行了两次,也知道执行了顺序了,就可以加个全局变量,运行一次后再运行就跳出。代码如下。
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import javax.swing.*;
@SpringBootApplication
public class DemoApplication {
public static boolean OPEN = true;
public DemoApplication() {
if (!OPEN){
return;
}
OPEN = false;
System.out.println("im constructor");
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new DemoApplication();
createAndShowGUI();
}
});
SpringApplication.run(DemoApplication.class, args);
}
private static void createAndShowGUI() {
System.out.println("im static");
}
}
再看下执行结果:
im constructor
im static
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.6.RELEASE)
2019-08-04 14:43:53.563 INFO 8300 --- [ main] com.example.demo.DemoApplication : Starting DemoApplication on PC-20170518JWLD with PID 8300 (C:\Users\Administrator\Desktop\demo\target\classes started by Administrator in C:\Users\Administrator\Desktop\demo)
2019-08-04 14:43:53.567 INFO 8300 --- [ main] com.example.demo.DemoApplication : No active profile set, falling back to default profiles: default
2019-08-04 14:43:54.691 INFO 8300 --- [ main] com.example.demo.DemoApplication : Started DemoApplication in 1.757 seconds (JVM running for 2.616)
噔噔·······,只执行了一次,简单粗暴,哈哈。而且执行成功也是被new才执行的。下面说说,SpringApplication.run(DemoApplication.class, args);这个方法。先看上边的调用栈,,看看这个方法怎么调用的。
这里我先看了Spring Boot的启动流程这篇文章。
简单一句话就是:这个方法里面首先要创建一个SpringApplication对象实例(如果已创建则去执行。),然后调用这个创建好的SpringApplication的实例方法。
第二个办法:既然SpringApplication的构造函数会被执行两次,那就再写个类,去调用就好了。
第三个办法就是,写静态方法了。。。。