Analysis of function callback mechanism and classic application of function callback in Spring framework

  • The concept of callback function

       The callback function, as the name suggests, is: A calls B, and then B can call back the method in A. An example can be given as follows: I come home from get off work at night and turn on the lights to cook dinner with an electric rice cooker. I find that the electricity is out of service due to arrears. At this time, I pay the electricity bill through Alipay. After the electricity bill is paid successfully, Alipay needs to notify the power company that my electricity bill has been paid successfully. , and then I checked the electricity meter at home and found that the electricity bill was successfully paid, and I could continue to cook (just an example to illustrate the meaning of the callback function, the specific payment of electricity bills by Alipay is not necessarily implemented in this way).

 

  • sample code

Callback interface, after the electricity bill payment is successful, the client caller needs to be notified that the electricity bill payment is successful.

package com.test;

/**
 * Callback interface
 */
public interface ICallBackAction {
    void doOnLight(int number);
}

 

 Specific payment interface

/**
 * Interface for paying fees
 */
public interface IPayFees {

    void executor(ICallBackAction action);
}

 

 The specific implementation class for paying electricity bills. The client calls this method to pay electricity bills. After successful payment, it needs to call back the method in the class object instance of the callback function passed in by the client, which is called callback function for short.

package com.test;

/**
 * Implementation template class for paying electricity bills
 */
public class PayElectricityFeesTemplate implements IPayFees{

    private int money ;
    
    public PayElectricityFeesTemplate (int money)
        this.money = money;
    }
    
    @Override
    public void executor(ICallBackAction action) {
        System.out.println("Pay electricity bill" + money + "Yuan");
        System.out.println("0.5 yuan per kilowatt hour, total" + money * 2 + "electricity kilowatt hour, recharge is successful");
        action.doOnLight(money * 2);
    }

    
}

 test class

package com.test;

public class CallBackMain {

    public static void main(String[] args) {
        final CallBackMain main = new CallBackMain();
        System.out.println("Start cooking lunch with the rice cooker......");
        System.out.println("It was found that there was a power failure at home, and it was found that there was no charging fee for two months, and the payment was in arrears......");
        System.out.println("Start charging fee");
        main.doBeginPayFee(100);
    }
    
    
    
    private void doBeginPayFee(int money) {
        
        IPayFees instance = new PayElectricityFeesTemplate(money);
        instance.executor(new ICallBackAction(){
           //The specific callback function, and the callee calls this method after executing the specific logic. can also be called
           //The relevant parameters in the method are passed to the caller
            @Override
            public void doOnLight(int number) {
                System.out.println("The electricity bill is recharged successfully, there is a call, and there is a total remaining" + number + "kWh");
            }
        });
    }
}

 

 

  • JdbcTemplate application in Spring

    JdbcTemplate.java is a template class for database operations in Spring, which is mainly used for database operations related functions, such as obtaining

    A template class for common logic such as database connection and timeout processing.

org.springframework.jdbc.core.JdbcTemplate.java


        /**
         * The execute method is mainly used for the execution entry when the caller needs to perform database operations
         * This method will uniformly obtain the underlying connection of the database, and then return it to the caller through the callback interface to execute the specific database
         * operate.
         * The advantage of this is that the connection operation of obtaining the database is uniformly encapsulated into the template class, and the caller does not need to explicitly obtain the database
         * The connection returns the connection through the callback function to operate the database. In this way, the code is reused and decoupled.
         * effect, the caller only needs to care about its own execution business.
         */
	@Override
	public <T> T execute(ConnectionCallback<T> action) throws DataAccessException {
		Assert.notNull(action, "Callback object must not be null");

		Connection con = DataSourceUtils.getConnection(getDataSource());
		try {
			Connection conToUse = con;
			if (this.nativeJdbcExtractor != null) {
				// Extract native JDBC Connection, castable to OracleConnection or the like.
				conToUse = this.nativeJdbcExtractor.getNativeConnection (con);
			}
			else {
				// Create close-suppressing Connection proxy, also preparing returned Statements.
				conToUse = createConnectionProxy (con);
			}
			return action.doInConnection (conToUse);
		}
		catch (SQLException ex) {
			// Release Connection early, to avoid potential connection pool deadlock
			// in the case when the exception translator hasn't been initialized yet.
			DataSourceUtils.releaseConnection(con, getDataSource());
			with = null;
			throw getExceptionTranslator().translate("ConnectionCallback", getSql(action), ex);
		}
		finally {
			DataSourceUtils.releaseConnection(con, getDataSource());
		}
	}

 

org.springframework.jdbc.core.simple.AbstractJdbcInsert.java

/**
	 * Delegate method to execute the insert, generating any number of keys.
	 */
	private KeyHolder executeInsertAndReturnKeyHolderInternal(final List<?> values) {
		.........
                .........
			else {
		  getJdbcTemplate().execute(new ConnectionCallback<Object>() {
	                             /**
                                      * Note the parameter conn object, this object is the callee through the callback function
                                     * The incoming value, so that the caller only needs to care about its own database operation business.
                                     */                                       @Override
					public Object doInConnection(Connection con) throws SQLException, DataAccessException {
						// Do the insert
						PreparedStatement ps = null;
						try {
							ps = con.prepareStatement(getInsertString());
							setParameterValues(ps, values, getInsertTypes());
							ps.executeUpdate();
						}
						finally {
							JdbcUtils.closeStatement(ps);
						}
						//Get the key
						Statement keyStmt = null;
						ResultSet rs = null;
						Map<String, Object> keys = new HashMap<String, Object>(1);
						try {
							keyStmt = con.createStatement();
							rs = keyStmt.executeQuery(keyQuery);
							if (rs.next()) {
								long key = rs.getLong(1);
								keys.put(getGeneratedKeyNames()[0], key);
								keyHolder.getKeyList().add(keys);
							}
						}
						finally {
							JdbcUtils.closeResultSet(rs);
							JdbcUtils.closeStatement(keyStmt);
						}
						return null;
					}
				});
			}
			return keyHolder;
		}
		return keyHolder;
	}

 

Summarize:

    The callback function is not only synchronous, but also asynchronous. There is no example here, the general pattern is the same.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326199409&siteId=291194637