Reputation: 20591
I have many methods like this:
Connection connection = null;
try {
connection = new Connection();
connection.connect();
.... // method body
} finally {
if (connection != null) {
connection.disconnect();
}
}
Can I exclude this part into apects (AspectJ)?
Upvotes: 0
Views: 542
Reputation: 200246
You can extract your connection management into an around-advice and make the contextual Connection
available to the business code by exposing it in a ThreadLocal
. Define a public class with a static property:
public class ConnectionHolder {
public static final ThreadLocal<Connection> connection = new ThreadLocal<>();
}
In the around advice you must set the ThreadLocal
to the open connection and make very sure you unconditionally clear it afterwards. This is the greatest pitfall with ThreadLocal
s: leaking objects into unrelated contexts. Also beware of child thread inheriting the ThreadLocal
(there was an issue with this in WebSphere once).
All in all, ThreadLocal
s are quite a dirty solution, but anything else will require you to go for a dependency-injection framework like Spring, configure request-scoped beans, etc., which would be a good idea, but will take more research on your part.
Upvotes: 2
Reputation: 33779
Alternatively, you can extract the connection plumbing using the template pattern to avoid copy / paste. The basic idea is something like:
abstract ConnectionTemplate {
private Connection connection = // ...
/**
* Method to be implementad by child classes
*/
public abstract void businessLogicCallback();
/**
* Template method that ensure that mandatory plumbing is executed
*/
public void doBusinessLogic() {
try {
openConnection();
// fetch single result, iterate across resultset, etc
businessLogicCallback();
finally {
closeConnection();
}
}
void openConnection() {
connection.open();
}
void closeConnection() {
if (connection != null) {
connection.close();
}
}
}
Now, implementing classes can be as simple as
class ImportantBusinessClass extends ConnectionTemplate {
@Override
public void businessLogicCallback() {
// do something important
}
}
And you use it like
ImportantBusinessClass importantClass = new ImportantBusinessClass();
importantClass.doBusinessLogic(); // opens connection, execute callback and closes connection
Spring framework uses this technique in some places, notably the JdbcTemplate deals with SQL, connections, mapping between rows and domain objects, etc. Please refer to the source code in GitHub for implementation details.
Upvotes: 0