如何将数据库连接合并到 AspectJ 中?

How do I incorporate database connection into AspectJ?

我需要将数据库连接和关闭方法放入 AspectJ class。目前我的添加方法如下所示:

public void addBookDetails(String name, String author, String publisher, int year, int price){

    Connection conn=null;
    DBConnection DBConn=new DBConnection();
    try {
        conn=DBConnection.createConnection();
        Statement statement=conn.createStatement();
        System.out.println("INSERT INTO Books " + "VALUES ('"+name+"', '"+author+"', '"+publisher+"', '"+year+"', '"+price+"')");
        statement.executeUpdate("INSERT INTO Books " + "VALUES ('"+name+"', '"+author+"', '"+publisher+"', '"+year+"', '"+price+"')");
        DBConn.closeConnection();
    } catch (SQLException e) {
        e.printStackTrace();
    }
}

如何将此 createConnection 和 closeConnection 方法作为 Aspect class?因为它们不属于 addBookDetails 的范围。请指教。如果我移动此方法,我不明白如何使用 "conn" 对象。因为这个 class.

中的 CreateStatement 方法需要它

也许你的意思是这样的?

实体classes:

这里我们有两个 classes,都没有操作 addDetails(..) 方法。我们希望方面在执行这些方法时拦截这些方法,并为它们神奇地 create/execute SQL 语句。

package de.scrum_master.app;

public class Book {
    public void addDetails(
        String name, String author, String publisher, int year, int price
    ) {}
}
package de.scrum_master.app;

public class Person {
    public void addDetails(
        String firstName, String lastName, int yearOfBirth
    ) {}
}

现在假设我们可以从 class 名称派生出 SQL table 名称,只需在其后附加一个复数 "s"。这将在稍后执行 SQL 魔术的方面变得重要。

数据库连接模型class:

这个 class 除了返回应用程序期望的对象外,没有什么特别的。我把它贴在这里是为了让这个例子可以编译和运行。

package de.scrum_master.app;

import java.sql.Array;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;

public class DBConnection {
    public void closeConnection() {}

    public static Connection createConnection() { return new Connection() {
            @Override public <T> T unwrap(Class<T> iface) throws SQLException { return null; }
            @Override public boolean isWrapperFor(Class<?> iface) throws SQLException { return false; }
            @Override public void setTypeMap(Map<String, Class<?>> map) throws SQLException {}
            @Override public void setTransactionIsolation(int level) throws SQLException {}
            @Override public void setSchema(String schema) throws SQLException {}
            @Override public Savepoint setSavepoint(String name) throws SQLException { return null; }
            @Override public Savepoint setSavepoint() throws SQLException { return null; }
            @Override public void setReadOnly(boolean readOnly) throws SQLException {}
            @Override public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {}
            @Override public void setHoldability(int holdability) throws SQLException {}
            @Override public void setClientInfo(String name, String value) throws SQLClientInfoException {}
            @Override public void setClientInfo(Properties properties) throws SQLClientInfoException {}
            @Override public void setCatalog(String catalog) throws SQLException {}
            @Override public void setAutoCommit(boolean autoCommit) throws SQLException {}
            @Override public void rollback(Savepoint savepoint) throws SQLException {}
            @Override public void rollback() throws SQLException {}
            @Override public void releaseSavepoint(Savepoint savepoint) throws SQLException {}
            @Override public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { return null; }
            @Override public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { return null; }
            @Override public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { return null; }
            @Override public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { return null; }
            @Override public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { return null; }
            @Override public PreparedStatement prepareStatement(String sql) throws SQLException { return null; }
            @Override public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { return null; }
            @Override public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { return null; }
            @Override public CallableStatement prepareCall(String sql) throws SQLException { return null; }
            @Override public String nativeSQL(String sql) throws SQLException { return null; }
            @Override public boolean isValid(int timeout) throws SQLException { return false; }
            @Override public boolean isReadOnly() throws SQLException { return false; }
            @Override public boolean isClosed() throws SQLException { return false; }
            @Override public SQLWarning getWarnings() throws SQLException { return null; }
            @Override public Map<String, Class<?>> getTypeMap() throws SQLException { return null; }
            @Override public int getTransactionIsolation() throws SQLException { return 0; }
            @Override public String getSchema() throws SQLException { return null; }
            @Override public int getNetworkTimeout() throws SQLException { return 0; }
            @Override public DatabaseMetaData getMetaData() throws SQLException { return null; }
            @Override public int getHoldability() throws SQLException { return 0; }
            @Override public String getClientInfo(String name) throws SQLException { return null; }
            @Override public Properties getClientInfo() throws SQLException { return null; }
            @Override public String getCatalog() throws SQLException { return null; }
            @Override public boolean getAutoCommit() throws SQLException { return false; }
            @Override public Struct createStruct(String typeName, Object[] attributes) throws SQLException { return null; }
            @Override public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { return null; }
            @Override public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { return null; }
            @Override public Statement createStatement() throws SQLException { return new Statement() {
                    @Override public <T> T unwrap(Class<T> iface) throws SQLException { return null; }
                    @Override public boolean isWrapperFor(Class<?> iface) throws SQLException { return false; }
                    @Override public void setQueryTimeout(int seconds) throws SQLException {}
                    @Override public void setPoolable(boolean poolable) throws SQLException {}
                    @Override public void setMaxRows(int max) throws SQLException {}
                    @Override public void setMaxFieldSize(int max) throws SQLException {}
                    @Override public void setFetchSize(int rows) throws SQLException {}
                    @Override public void setFetchDirection(int direction) throws SQLException {}
                    @Override public void setEscapeProcessing(boolean enable) throws SQLException {}
                    @Override public void setCursorName(String name) throws SQLException {}
                    @Override public boolean isPoolable() throws SQLException { return false; }
                    @Override public boolean isClosed() throws SQLException { return false; }
                    @Override public boolean isCloseOnCompletion() throws SQLException { return false; }
                    @Override public SQLWarning getWarnings() throws SQLException { return null; }
                    @Override public int getUpdateCount() throws SQLException { return 0; }
                    @Override public int getResultSetType() throws SQLException { return 0; }
                    @Override public int getResultSetHoldability() throws SQLException { return 0; }
                    @Override public int getResultSetConcurrency() throws SQLException { return 0; }
                    @Override public ResultSet getResultSet() throws SQLException { return null; }
                    @Override public int getQueryTimeout() throws SQLException { return 0; }
                    @Override public boolean getMoreResults(int current) throws SQLException { return false; }
                    @Override public boolean getMoreResults() throws SQLException { return false; }
                    @Override public int getMaxRows() throws SQLException { return 0; }
                    @Override public int getMaxFieldSize() throws SQLException { return 0; }
                    @Override public ResultSet getGeneratedKeys() throws SQLException { return null; }
                    @Override public int getFetchSize() throws SQLException { return 0; }
                    @Override public int getFetchDirection() throws SQLException { return 0; }
                    @Override public Connection getConnection() throws SQLException { return null; }
                    @Override public int executeUpdate(String sql, String[] columnNames) throws SQLException { return 0; }
                    @Override public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { return 0; }
                    @Override public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { return 0; }
                    @Override public int executeUpdate(String sql) throws SQLException { return 0; }
                    @Override public ResultSet executeQuery(String sql) throws SQLException { return null; }
                    @Override public int[] executeBatch() throws SQLException { return null; }
                    @Override public boolean execute(String sql, String[] columnNames) throws SQLException { return false; }
                    @Override public boolean execute(String sql, int[] columnIndexes) throws SQLException { return false; }
                    @Override public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { return false; }
                    @Override public boolean execute(String sql) throws SQLException { return false; }
                    @Override public void closeOnCompletion() throws SQLException {}
                    @Override public void close() throws SQLException {}
                    @Override public void clearWarnings() throws SQLException {}
                    @Override public void clearBatch() throws SQLException {}
                    @Override public void cancel() throws SQLException {}
                    @Override public void addBatch(String sql) throws SQLException {}
                };
            }
            @Override public SQLXML createSQLXML() throws SQLException { return null; }
            @Override public NClob createNClob() throws SQLException { return null; }
            @Override public Clob createClob() throws SQLException { return null; }
            @Override public Blob createBlob() throws SQLException { return null; }
            @Override public Array createArrayOf(String typeName, Object[] elements) throws SQLException { return null; }
            @Override public void commit() throws SQLException {}
            @Override public void close() throws SQLException {}
            @Override public void clearWarnings() throws SQLException {}
            @Override public void abort(Executor executor) throws SQLException {}
        };
    }
}

驱动申请:

package de.scrum_master.app;

public class Application {
    public static void main(String[] args) {
        new Book().addDetails("Gödel, Escher, Bach: An Eternal Golden Braid", "Douglas R. Hofstadter", "Basic Books", 1979, 990);
        new Book().addDetails("Cryptonomicon", "Neal Stephenson", "Avon", 1999, 990);
        new Person().addDetails("Albert", "Einstein", 1879);
        new Person().addDetails("Werner", "Heisenberg", 1901);
    }
}

看点:

方面有两个辅助方法负责

  • 创建 SQL 语句文本和
  • 打开数据库连接,执行SQL语句,然后再次关闭连接。
package de.scrum_master.aspect;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;

import de.scrum_master.app.DBConnection;

public aspect SqlUpdater {
    void around() : execution(public void addDetails(..)) {
        System.out.println(thisJoinPoint);
        String sqlText = createSqlStatement(thisJoinPoint.getTarget().getClass(), thisJoinPoint.getArgs());
        System.out.println("  " + sqlText);
        connectToDbAndUpdate(sqlText);
        proceed();
    }

    private static String createSqlStatement(Class<?> targetClass, Object[] args) {
        StringBuilder sqlText = new StringBuilder("INSERT INTO ");
        sqlText.append(targetClass.getSimpleName() + "s ").append("VALUES (");
        int argSize = args == null ? 0 : args.length;
        int i = 0;
        for (Object arg : args) {
            i++;
            sqlText.append(arg instanceof String ? "'" : "").append(arg);
            if (i < argSize)
                sqlText.append(arg instanceof String ? "', " : ", ");
            else
                sqlText.append(arg instanceof String ? "'" : "");
        }
        sqlText.append(")");
        return sqlText.toString();
    }

    private static void connectToDbAndUpdate(String sqlText) {
        Connection sqlConnection = null;
        DBConnection dbConnection = new DBConnection();
        try {
            sqlConnection = DBConnection.createConnection();
            Statement sqlStatement = sqlConnection.createStatement();
            sqlStatement.executeUpdate(sqlText);
            dbConnection.closeConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

控制台输出:

execution(void de.scrum_master.app.Book.addDetails(String, String, String, int, int))
  INSERT INTO Books VALUES ('Gödel, Escher, Bach: An Eternal Golden Braid', 'Douglas R. Hofstadter', 'Basic Books', 1979, 990)
execution(void de.scrum_master.app.Book.addDetails(String, String, String, int, int))
  INSERT INTO Books VALUES ('Cryptonomicon', 'Neal Stephenson', 'Avon', 1999, 990)
execution(void de.scrum_master.app.Person.addDetails(String, String, int))
  INSERT INTO Persons VALUES ('Albert', 'Einstein', 1879)
execution(void de.scrum_master.app.Person.addDetails(String, String, int))
  INSERT INTO Persons VALUES ('Werner', 'Heisenberg', 1901)

如果您不理解示例代码,请随时提出后续问题。