Thursday, March 28, 2024
HomeJavaJava and dynamic Proxies - Java Code Geeks

Java and dynamic Proxies – Java Code Geeks


Dynamic proxies in Java is a straightforward and really helpful function.

Normally we create an interface implementation after which compilation is concerned. With dynamic proxies we are able to implement an inventory of interfaces at runtime. A proxy object can be created, when a way is invoked on that proxy occasion, the strategies invoked can be forwarded to an invocation handler specified.

This could have numerous usages. A typical use case could be for a java interface which we are able to use a proxy and intercept the calls to the strategies invoked.

Supposing we now have a JDBC connection pool and we need to have one thing like a micrometer counter. On getting a connection the counter will enhance, thus we are able to establish the speed of buying connections in our software.

We will use a proxy for that.

Let’s first add a docker container for Postgresql utilizing Docker Compose.

model: '3.1'

companies:
  postgres:
    picture: postgres
    restart: at all times
    setting:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
    ports:
      - 5432:5432

We will run with the next command

You will discover extra on Compose on the Builders Important Information to Docker Compose.

Let’s add our dependencies to our Java undertaking

<dependencies>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <model>42.5.1</model>
        </dependency>
        <dependency>
            <groupId>com.zaxxer</groupId>
            <artifactId>HikariCP</artifactId>
            <model>4.0.3</model>
            <scope>compile</scope>
        </dependency>
    </dependencies>

Now may even add a small snippet.

package deal com.instance.gkatzioura.proxy;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

public class Utility {

    public static void fundamental(String[] args) throws SQLException {
        Properties props = new Properties();

        props.setProperty("dataSourceClassName", "org.postgresql.ds.PGSimpleDataSource");
        props.setProperty("dataSource.person", "postgres");
        props.setProperty("dataSource.password", "postgres");
        props.setProperty("dataSource.databaseName", "postgres");
        props.put("dataSource.logWriter", new PrintWriter(System.out));

        HikariConfig config = new HikariConfig(props);
        
        attempt(HikariDataSource ds = new HikariDataSource(config)) {
            attempt(Connection connection = ds.getConnection()) {
                System.out.println("Needs to be printed after the proxy");       
            }
        }
    }

}

We will look at the DataSource interface of Java on the supply code. We will see the strategy of curiosity, getConnection, current.

public interface DataSource  extends CommonDataSource, Wrapper {

    Connection getConnection() throws SQLException;
    ...
}

As a substitute of making an interface implementation and having to implement all these strategies after which delegate them to the precise DataSource occasion, we will as an alternative use a proxy and add actions solely to the strategy of curiosity, in our case getConnection.

We will implement an InvocationHandler.

package deal com.instance.gkatzioura.proxy;

import java.lang.replicate.InvocationHandler;
import java.lang.replicate.Technique;
import java.lang.replicate.Proxy;

import javax.sql.DataSource;

public class GetConnectionHandler implements InvocationHandler {

    personal closing DataSource dataSource;

    public GetConnectionHandler(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    @Override
    public Object invoke(Object proxy, Technique technique, Object[] args) throws Throwable {
        if (technique.getName().equals("getConnection")) {
            System.out.println("Referred to as earlier than precise technique");

        }

        return technique.invoke(dataSource, args);
    }

    public static DataSource proxy(DataSource dataSource) {
        return (DataSource) Proxy.newProxyInstance(DataSource.class.getClassLoader(), new Class[]{DataSource.class}, new GetConnectionHandler(dataSource));
    }

}

Let’s break it down.

The invocation handler can be referred to as for the strategy of an interface specified. When an interface technique is invoked it’s our selection how we will deal with it. In our case we will print a easy message after which we will execute the corresponding technique to our goal occasion.

Additionally we now have a static manufacturing facility specified which shall proxy the article implementing the interface of curiosity. A brand new proxy occasion can be created, it would implement the interfaces offered and the calls in the direction of the proxy occasion can be handed to the handler we offered.

Let’s revisit our fundamental technique.

package deal com.instance.gkatzioura.proxy;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

import javax.sql.DataSource;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

import static com.instance.gkatzioura.proxy.GetConnectionHandler.proxy;

public class Utility {

    public static void fundamental(String[] args) throws SQLException {
        Properties props = new Properties();

        props.setProperty("dataSourceClassName", "org.postgresql.ds.PGSimpleDataSource");
        props.setProperty("dataSource.person", "postgres");
        props.setProperty("dataSource.password", "postgres");
        props.setProperty("dataSource.databaseName", "postgres");
        props.put("dataSource.logWriter", new PrintWriter(System.out));

        HikariConfig config = new HikariConfig(props);

        attempt(HikariDataSource ds = new HikariDataSource(config)) {
            DataSource dataSource = proxy(ds);
            attempt(Connection connection = dataSource.getConnection()) {
                System.out.println("Needs to be printed after the proxy");
            }
        }
    }

}

We wrapped the HikariDataSource with a Dynamic Proxy and if we run this system we should always see the next output.

Referred to as earlier than precise technique
Needs to be printed after the proxy

If we break it down, we created a proxy with the DataSource interface. By creating the proxy we offered an invocation handler which shall print a message earlier than the getConnection technique is invoked. The getConnection can be invoked by the precise implementation of the DataSource interface that we specified on the InvocationHandler.

You will discover the supply code on GitHub.

Printed on Java Code Geeks with permission by Emmanouil Gkatziouras, companion at our JCG program. See the unique article right here: Java and dynamic Proxies

Opinions expressed by Java Code Geeks contributors are their very own.

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments