1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.beans.factory.support;
18
19 import java.lang.reflect.Constructor;
20 import java.lang.reflect.InvocationTargetException;
21 import java.lang.reflect.Method;
22 import java.security.AccessController;
23 import java.security.PrivilegedAction;
24 import java.security.PrivilegedExceptionAction;
25
26 import org.springframework.beans.BeanInstantiationException;
27 import org.springframework.beans.BeanUtils;
28 import org.springframework.beans.factory.BeanFactory;
29 import org.springframework.beans.factory.config.ConfigurableBeanFactory;
30 import org.springframework.util.ReflectionUtils;
31 import org.springframework.util.StringUtils;
32
33
34
35
36
37
38
39
40
41
42
43 public class SimpleInstantiationStrategy implements InstantiationStrategy {
44
45 private static final ThreadLocal<Method> currentlyInvokedFactoryMethod = new ThreadLocal<Method>();
46
47
48
49
50
51
52
53 public static Method getCurrentlyInvokedFactoryMethod() {
54 return currentlyInvokedFactoryMethod.get();
55 }
56
57
58 @Override
59 public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
60
61 if (bd.getMethodOverrides().isEmpty()) {
62 Constructor<?> constructorToUse;
63 synchronized (bd.constructorArgumentLock) {
64 constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
65 if (constructorToUse == null) {
66 final Class<?> clazz = bd.getBeanClass();
67 if (clazz.isInterface()) {
68 throw new BeanInstantiationException(clazz, "Specified class is an interface");
69 }
70 try {
71 if (System.getSecurityManager() != null) {
72 constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>() {
73 @Override
74 public Constructor<?> run() throws Exception {
75 return clazz.getDeclaredConstructor((Class[]) null);
76 }
77 });
78 }
79 else {
80 constructorToUse = clazz.getDeclaredConstructor((Class[]) null);
81 }
82 bd.resolvedConstructorOrFactoryMethod = constructorToUse;
83 }
84 catch (Exception ex) {
85 throw new BeanInstantiationException(clazz, "No default constructor found", ex);
86 }
87 }
88 }
89 return BeanUtils.instantiateClass(constructorToUse);
90 }
91 else {
92
93 return instantiateWithMethodInjection(bd, beanName, owner);
94 }
95 }
96
97
98
99
100
101
102
103 protected Object instantiateWithMethodInjection(RootBeanDefinition bd, String beanName, BeanFactory owner) {
104 throw new UnsupportedOperationException("Method Injection not supported in SimpleInstantiationStrategy");
105 }
106
107 @Override
108 public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner,
109 final Constructor<?> ctor, Object... args) {
110
111 if (bd.getMethodOverrides().isEmpty()) {
112 if (System.getSecurityManager() != null) {
113
114 AccessController.doPrivileged(new PrivilegedAction<Object>() {
115 @Override
116 public Object run() {
117 ReflectionUtils.makeAccessible(ctor);
118 return null;
119 }
120 });
121 }
122 return BeanUtils.instantiateClass(ctor, args);
123 }
124 else {
125 return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);
126 }
127 }
128
129
130
131
132
133
134
135 protected Object instantiateWithMethodInjection(RootBeanDefinition bd, String beanName, BeanFactory owner,
136 Constructor<?> ctor, Object... args) {
137
138 throw new UnsupportedOperationException("Method Injection not supported in SimpleInstantiationStrategy");
139 }
140
141 @Override
142 public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner,
143 Object factoryBean, final Method factoryMethod, Object... args) {
144
145 try {
146 if (System.getSecurityManager() != null) {
147 AccessController.doPrivileged(new PrivilegedAction<Object>() {
148 @Override
149 public Object run() {
150 ReflectionUtils.makeAccessible(factoryMethod);
151 return null;
152 }
153 });
154 }
155 else {
156 ReflectionUtils.makeAccessible(factoryMethod);
157 }
158
159 Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();
160 try {
161 currentlyInvokedFactoryMethod.set(factoryMethod);
162 return factoryMethod.invoke(factoryBean, args);
163 }
164 finally {
165 if (priorInvokedFactoryMethod != null) {
166 currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
167 }
168 else {
169 currentlyInvokedFactoryMethod.remove();
170 }
171 }
172 }
173 catch (IllegalArgumentException ex) {
174 throw new BeanInstantiationException(factoryMethod.getReturnType(),
175 "Illegal arguments to factory method '" + factoryMethod.getName() + "'; " +
176 "args: " + StringUtils.arrayToCommaDelimitedString(args), ex);
177 }
178 catch (IllegalAccessException ex) {
179 throw new BeanInstantiationException(factoryMethod.getReturnType(),
180 "Cannot access factory method '" + factoryMethod.getName() + "'; is it public?", ex);
181 }
182 catch (InvocationTargetException ex) {
183 String msg = "Factory method '" + factoryMethod.getName() + "' threw exception";
184 if (bd.getFactoryBeanName() != null && owner instanceof ConfigurableBeanFactory &&
185 ((ConfigurableBeanFactory) owner).isCurrentlyInCreation(bd.getFactoryBeanName())) {
186 msg = "Circular reference involving containing bean '" + bd.getFactoryBeanName() + "' - consider " +
187 "declaring the factory method as static for independence from its containing instance. " + msg;
188 }
189 throw new BeanInstantiationException(factoryMethod.getReturnType(), msg, ex.getTargetException());
190 }
191 }
192
193 }