0
# Programmatic Weaving
1
2
The AspectJ Weaver provides programmatic APIs for embedding aspect weaving capabilities directly into applications. This allows developers to weave classes on-demand or integrate weaving into custom class loading mechanisms.
3
4
## Core Weaving Classes
5
6
### WeavingAdaptor
7
8
Main adaptor for embedding AspectJ weaving capabilities.
9
10
```java { .api }
11
public class WeavingAdaptor {
12
public WeavingAdaptor(WeavingClassLoader loader);
13
public WeavingAdaptor(GeneratedClassHandler handler, URL[] classURLs, URL[] aspectURLs);
14
public void addURL(URL url);
15
public byte[] weaveClass(String name, byte[] bytes) throws IOException;
16
public byte[] weaveClass(String name, byte[] bytes, boolean mustWeave) throws IOException;
17
public IMessageHolder getMessageHolder();
18
public String getContextId();
19
}
20
```
21
22
#### Constructors
23
24
```java { .api }
25
public WeavingAdaptor(WeavingClassLoader loader)
26
```
27
28
Creates a weaving adaptor with a weaving class loader.
29
30
**Parameters:**
31
- `loader` - Class loader implementing WeavingClassLoader interface
32
33
```java { .api }
34
public WeavingAdaptor(GeneratedClassHandler handler, URL[] classURLs, URL[] aspectURLs)
35
```
36
37
Creates a weaving adaptor with explicit URLs and class handler.
38
39
**Parameters:**
40
- `handler` - Handler for generated classes during weaving
41
- `classURLs` - URLs containing classes to be woven
42
- `aspectURLs` - URLs containing aspect definitions
43
44
#### Methods
45
46
```java { .api }
47
public void addURL(URL url)
48
```
49
50
Adds a URL to the weaving classpath.
51
52
**Parameters:**
53
- `url` - URL to add to classpath
54
55
```java { .api }
56
public byte[] weaveClass(String name, byte[] bytes) throws IOException
57
```
58
59
Weaves a class using the configured aspects.
60
61
**Parameters:**
62
- `name` - Fully qualified class name (e.g., "com.example.MyClass")
63
- `bytes` - Original class bytes
64
65
**Returns:** Woven class bytes or original bytes if no weaving applied
66
67
**Throws:** `IOException` if weaving fails
68
69
```java { .api }
70
public byte[] weaveClass(String name, byte[] bytes, boolean mustWeave) throws IOException
71
```
72
73
Weaves a class with optional forced weaving.
74
75
**Parameters:**
76
- `name` - Fully qualified class name
77
- `bytes` - Original class bytes
78
- `mustWeave` - If true, forces weaving even if no aspects match
79
80
**Returns:** Woven class bytes
81
82
**Throws:** `IOException` if weaving fails
83
84
```java { .api }
85
public IMessageHolder getMessageHolder()
86
```
87
88
Returns the message holder for weaving messages and warnings.
89
90
**Returns:** IMessageHolder instance containing weaving messages
91
92
```java { .api }
93
public String getContextId()
94
```
95
96
Returns the context identifier for this weaving adaptor.
97
98
**Returns:** String identifier for the weaving context
99
100
### ClassLoaderWeavingAdaptor
101
102
Extended weaving adaptor with classloader-specific functionality.
103
104
```java { .api }
105
public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {
106
// Additional classloader-specific methods
107
}
108
```
109
110
## Core Preprocessor Interface
111
112
### ClassPreProcessor
113
114
Generic preprocessor interface for separating AspectJ weaving from JVMTI interfaces.
115
116
```java { .api }
117
public interface ClassPreProcessor {
118
void initialize();
119
byte[] preProcess(String className, byte[] bytes, ClassLoader classLoader,
120
ProtectionDomain protectionDomain);
121
void prepareForRedefinition(ClassLoader loader, String className);
122
}
123
```
124
125
#### initialize
126
127
Initializes the preprocessor.
128
129
```java { .api }
130
void initialize()
131
```
132
133
#### preProcess
134
135
Preprocesses class bytes, applying weaving transformations.
136
137
```java { .api }
138
byte[] preProcess(String className, byte[] bytes, ClassLoader classLoader,
139
ProtectionDomain protectionDomain)
140
```
141
142
**Parameters:**
143
- `className` - Name of class being processed
144
- `bytes` - Original class bytes
145
- `classLoader` - ClassLoader defining the class
146
- `protectionDomain` - Security protection domain
147
148
**Returns:** Processed class bytes
149
150
#### prepareForRedefinition
151
152
Prepares for class redefinition during hotswap scenarios.
153
154
```java { .api }
155
void prepareForRedefinition(ClassLoader loader, String className)
156
```
157
158
**Parameters:**
159
- `loader` - ClassLoader containing the class
160
- `className` - Name of class being redefined
161
162
### Aj
163
164
Main preprocessor implementation adapting between the preprocessor interface and AspectJ weaver.
165
166
```java { .api }
167
public class Aj implements ClassPreProcessor {
168
public Aj();
169
public Aj(IWeavingContext context);
170
public void initialize();
171
public byte[] preProcess(String className, byte[] bytes, ClassLoader classLoader,
172
ProtectionDomain protectionDomain);
173
}
174
```
175
176
#### Constructors
177
178
```java { .api }
179
public Aj()
180
```
181
182
Creates an Aj preprocessor with default weaving context.
183
184
```java { .api }
185
public Aj(IWeavingContext context)
186
```
187
188
Creates an Aj preprocessor with custom weaving context.
189
190
**Parameters:**
191
- `context` - Custom weaving context for multi-classloader environments
192
193
## Usage Examples
194
195
### Basic Programmatic Weaving
196
197
```java
198
import org.aspectj.weaver.tools.WeavingAdaptor;
199
import java.io.FileInputStream;
200
import java.io.IOException;
201
202
public class BasicWeavingExample {
203
public static void main(String[] args) throws IOException {
204
// Create weaving adaptor
205
WeavingAdaptor adaptor = new WeavingAdaptor(
206
null, // GeneratedClassHandler
207
new URL[]{new URL("file:///path/to/classes/")}, // Class URLs
208
new URL[]{new URL("file:///path/to/aspects/")} // Aspect URLs
209
);
210
211
// Read original class bytes
212
byte[] originalBytes = readClassBytes("com.example.MyClass");
213
214
// Weave the class
215
byte[] wovenBytes = adaptor.weaveClass("com.example.MyClass", originalBytes);
216
217
// Use the woven bytes (e.g., save to file or define class)
218
saveWovenClass("com.example.MyClass", wovenBytes);
219
220
// Check for weaving messages
221
IMessageHolder messages = adaptor.getMessageHolder();
222
if (messages.hasAnyMessage(IMessage.ERROR)) {
223
System.err.println("Weaving errors occurred");
224
}
225
}
226
227
private static byte[] readClassBytes(String className) throws IOException {
228
// Implementation to read class bytes from file system
229
String path = className.replace('.', '/') + ".class";
230
return Files.readAllBytes(Paths.get(path));
231
}
232
233
private static void saveWovenClass(String className, byte[] bytes) throws IOException {
234
// Implementation to save woven bytes
235
String path = "woven/" + className.replace('.', '/') + ".class";
236
Files.write(Paths.get(path), bytes);
237
}
238
}
239
```
240
241
### Custom Class Loading with Weaving
242
243
```java
244
import org.aspectj.weaver.tools.WeavingAdaptor;
245
246
public class WeavingClassLoader extends URLClassLoader {
247
private final WeavingAdaptor weavingAdaptor;
248
249
public WeavingClassLoader(URL[] urls, ClassLoader parent) {
250
super(urls, parent);
251
this.weavingAdaptor = new WeavingAdaptor(this);
252
}
253
254
@Override
255
protected Class<?> findClass(String name) throws ClassNotFoundException {
256
try {
257
// Get original class bytes
258
byte[] originalBytes = getClassBytes(name);
259
260
// Weave the class
261
byte[] wovenBytes = weavingAdaptor.weaveClass(name, originalBytes);
262
263
// Define the woven class
264
return defineClass(name, wovenBytes, 0, wovenBytes.length);
265
266
} catch (IOException e) {
267
throw new ClassNotFoundException("Failed to weave class: " + name, e);
268
}
269
}
270
271
private byte[] getClassBytes(String name) throws IOException {
272
String resourceName = name.replace('.', '/') + ".class";
273
InputStream is = getResourceAsStream(resourceName);
274
if (is == null) {
275
throw new IOException("Class not found: " + name);
276
}
277
return is.readAllBytes();
278
}
279
}
280
```
281
282
### Preprocessor Integration
283
284
```java
285
import org.aspectj.weaver.loadtime.Aj;
286
import org.aspectj.weaver.loadtime.ClassPreProcessor;
287
288
public class CustomPreprocessorExample {
289
private final ClassPreProcessor processor;
290
291
public CustomPreprocessorExample() {
292
this.processor = new Aj();
293
processor.initialize();
294
}
295
296
public byte[] processClass(String className, byte[] originalBytes,
297
ClassLoader loader) {
298
return processor.preProcess(className, originalBytes, loader, null);
299
}
300
301
public void handleClassRedefinition(ClassLoader loader, String className) {
302
processor.prepareForRedefinition(loader, className);
303
}
304
}
305
```
306
307
### Error Handling and Diagnostics
308
309
```java
310
import org.aspectj.bridge.IMessage;
311
import org.aspectj.bridge.IMessageHolder;
312
313
public class WeavingDiagnostics {
314
public static void checkWeavingResults(WeavingAdaptor adaptor) {
315
IMessageHolder messages = adaptor.getMessageHolder();
316
317
// Check for errors
318
if (messages.hasAnyMessage(IMessage.ERROR)) {
319
System.err.println("Weaving errors:");
320
for (IMessage message : messages.getMessages(IMessage.ERROR, true)) {
321
System.err.println(" " + message.getMessage());
322
}
323
}
324
325
// Check for warnings
326
if (messages.hasAnyMessage(IMessage.WARNING)) {
327
System.out.println("Weaving warnings:");
328
for (IMessage message : messages.getMessages(IMessage.WARNING, true)) {
329
System.out.println(" " + message.getMessage());
330
}
331
}
332
333
// Check for info messages
334
if (messages.hasAnyMessage(IMessage.INFO)) {
335
System.out.println("Weaving info:");
336
for (IMessage message : messages.getMessages(IMessage.INFO, true)) {
337
System.out.println(" " + message.getMessage());
338
}
339
}
340
}
341
}
342
```
343
344
## Configuration Options
345
346
### System Properties
347
348
- **`WeavingAdaptor.WEAVING_ADAPTOR_VERBOSE`**: Enable verbose weaving output
349
- **`WeavingAdaptor.SHOW_WEAVE_INFO_PROPERTY`**: Show detailed weave information
350
- **`WeavingAdaptor.TRACE_MESSAGES_PROPERTY`**: Enable message tracing
351
352
### Programmatic Configuration
353
354
```java
355
// Enable verbose output
356
System.setProperty(WeavingAdaptor.WEAVING_ADAPTOR_VERBOSE, "true");
357
358
// Create adaptor with verbose settings
359
WeavingAdaptor adaptor = new WeavingAdaptor(classLoader);
360
```
361
362
## Performance Considerations
363
364
1. **Reuse WeavingAdaptor**: Create once and reuse for multiple classes
365
2. **Batch Processing**: Process multiple classes in a single session
366
3. **Caching**: Use WeavedClassCache for repeated weaving operations
367
4. **Memory Management**: Monitor memory usage during large weaving operations
368
369
## Troubleshooting
370
371
### Common Issues
372
373
1. **ClassNotFoundException**: Ensure all required classes and aspects are on the classpath
374
2. **IOException during weaving**: Check class format and aspect compatibility
375
3. **Performance degradation**: Consider enabling caching for repeated operations
376
377
### Debug Output
378
379
```java
380
// Enable debug output
381
System.setProperty("org.aspectj.weaver.showWeaveInfo", "true");
382
System.setProperty("aj.weaving.verbose", "true");
383
```