是否有可能在java中监听所有对象的创建?

时间:2016-01-17 14:52:24

标签: java

在Java中是否可以设置在创建任何对象时调用的默认侦听器?

类似的东西:

public static void main(String[] args) {
    setInstanceListener(listener); // this method doesn't exists
    MyObject obj = new MyObject(); // the new keyword now call listener()
    OtherObject oo = new OtherObject(); // same here
}

public static void listener(Object newObject) {
    // do something with the created object
}

1 个答案:

答案 0 :(得分:1)

如果您已准备好使用某些框架作为AspectJ,那么它非常简单。 在此,我将举一个使用Maven的例子。

首先是pom:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>dummy.listener</groupId>
    <artifactId>dummy.listener</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <description>
      Is it possible in java to listen all objects creation?
      http://stackoverflow.com/questions/34839701/is-it-possible-in-java-to-listen-all-objects-creation
    </description>

    <properties>

        <main.class>dummy.listener.MainApp</main.class>

        <jdk.version>1.7</jdk.version>
        <project.encoding>UTF-8</project.encoding>

        <project.build.sourceEncoding>${project.encoding}</project.build.sourceEncoding>
        <project.reporting.outputEncoding>${project.encoding}</project.reporting.outputEncoding>

        <maven.compiler.source>${jdk.version}</maven.compiler.source>
        <maven.compiler.target>${jdk.version}</maven.compiler.target>
        <maven.compiler.compilerVersion>${jdk.version}</maven.compiler.compilerVersion>
        <maven.compiler.fork>true</maven.compiler.fork>
        <maven.compiler.verbose>true</maven.compiler.verbose>
        <maven.compiler.optimize>true</maven.compiler.optimize>
        <maven.compiler.debug>true</maven.compiler.debug>

        <maven.jar.plugin.version>2.6</maven.jar.plugin.version>
        <maven.antrun.plugin.version>1.8</maven.antrun.plugin.version>
        <aspectj.maven.plugin.version>1.8</aspectj.maven.plugin.version>

        <aspectj.version>1.8.7</aspectj.version>
        <slf4j.version>1.7.13</slf4j.version>
    </properties>

    <dependencies>
        <!-- compile time weaving -->

        <!-- required to avoid warning from aspectj-maven-plugin, 
             even if aspectjweaver is also a dependency -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>${aspectj.version}</version>
        </dependency>

        <!-- aspectjrt is only a subset of aspectjweaver -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>${aspectj.version}</version>
        </dependency>

        <!-- logging -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>${slf4j.version}</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
            </plugin>
        </plugins>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>aspectj-maven-plugin</artifactId>
                    <version>${aspectj.maven.plugin.version}</version>
                    <configuration>
                        <complianceLevel>${jdk.version}</complianceLevel>
                        <showWeaveInfo>true</showWeaveInfo>
                    </configuration>
                    <executions>
                        <execution>
                            <goals>
                                <goal>compile</goal>
                                <goal>test-compile</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

    <profiles>
    <profile>
            <id>class-antrun</id>
            <build>
                <plugins>
                    <plugin>
                        <artifactId>maven-antrun-plugin</artifactId>
                        <version>${maven.antrun.plugin.version}</version>
                        <configuration>
                            <target>
                                <java fork="true" classname="${main.class}">
                                    <classpath refid="maven.compile.classpath" />
                                </java>
                            </target>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>
        <profile>
            <id>only-under-eclipse</id>
            <activation>
                <property>
                    <name>m2e.version</name>
                </property>
            </activation>
            <build>
                <pluginManagement>
                    <plugins>
                        <plugin>
                            <groupId>org.eclipse.m2e</groupId>
                            <artifactId>lifecycle-mapping</artifactId>
                            <version>1.0.0</version>
                            <configuration>
                                <lifecycleMappingMetadata>
                                    <pluginExecutions>
                                        <pluginExecution>
                                            <pluginExecutionFilter>
                                                <groupId>org.codehaus.mojo</groupId>
                                                <artifactId>aspectj-maven-plugin</artifactId>
                                                <versionRange>[${aspectj.maven.plugin.version},)</versionRange>
                                                <goals>
                                                    <goal>compile</goal>
                                                    <goal>test-compile</goal>
                                                </goals>
                                            </pluginExecutionFilter>
                                            <action>
                                                <ignore />
                                            </action>
                                        </pluginExecution>
                                    </pluginExecutions>
                                </lifecycleMappingMetadata>
                            </configuration>
                        </plugin>
                    </plugins>
                </pluginManagement>
            </build>
        </profile>
    </profiles>

</project>

然后是主要课程:

package dummy.listener;

import dummy.listener.model.MyObject1;
import dummy.listener.model.MyObject2;

public class MainApp {
    public static void main(final String[] args) {
        new MyObject1();
        new MyObject2();
    }

}

编织工作由以下人员完成:

package dummy.listener;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import dummy.listener.model.MyObject1;
import dummy.listener.model.MyObject2;

@Aspect
public class AspectjDemo
{
    private final Logger log = LoggerFactory.getLogger(AspectjDemo.class);

    @AfterReturning(pointcut="call(dummy.listener.model.*.new(..))", returning="result")
    public void doSomethingAfterNewModelCreation(JoinPoint joinPoint , Object result) {
        log.info("[AspectJ] Log after creation of " + result.getClass());
        if (/*result instanceof MyObject1*/ MyObject1.class.isAssignableFrom(result.getClass())) {
            MyObject1 mo = (MyObject1) result;
            log.info("Name: " + mo.getName());
        } else if (/*result instanceof MyObject2*/ MyObject2.class.isAssignableFrom(result.getClass())) {
            MyObject2 mo = (MyObject2) result;
            log.info("Location: " + mo.getLocation());
        }
    }
}

现在添加一些豚鼠类:

package dummy.listener.model;

public class MyObject1 {

    public String getName() {
        return "myObject1 name";
    }

}


package dummy.listener.model;

public class MyObject2 {

    public String getLocation() {
        return "myObject2 location";
    }

}

使用Maven完成,编译和启动主类:

mvn clean compile antrun:run -Pclass-antrun

你应该有类似的东西:

[...]
[INFO] --- aspectj-maven-plugin:1.8:compile (default) @ dummy.listener ---
[INFO] Showing AJC message detail for messages of types: [error, warning, fail]
[INFO] Join point 'constructor-call(void dummy.listener.model.MyObject1.<init>())' in Type 'dummy.listener.MainApp' (MainApp.java:8) advised by afterReturning advice from 'dummy.listener.AspectjDemo' (AspectjDemo.java:18)
[INFO] Join point 'constructor-call(void dummy.listener.model.MyObject2.<init>())' in Type 'dummy.listener.MainApp' (MainApp.java:9) advised by afterReturning advice from 'dummy.listener.AspectjDemo' (AspectjDemo.java:18)
[INFO] 
[INFO] --- maven-antrun-plugin:1.8:run (default-cli) @ dummy.listener ---
[INFO] Executing tasks

main:
     [java] [main] INFO dummy.listener.AspectjDemo - [AspectJ] Log after creation of class dummy.listener.model.MyObject1
     [java] [main] INFO dummy.listener.AspectjDemo - Name: myObject1 name
     [java] [main] INFO dummy.listener.AspectjDemo - [AspectJ] Log after creation of class dummy.listener.model.MyObject2
     [java] [main] INFO dummy.listener.AspectjDemo - Location: myObject2 location
[INFO] Executed tasks
[...]

那就是它。希望它能帮到你。