Почему конструктор выполняется только один раз в Spring AOP
Я пытаюсь понять весну. Я прочитал этот весенний документ. В нем говорится, что конструктор аспекта выполняется дважды, один раз для исходного объекта класса и другой для объекта-посредника. Но когда я попытался создать свой собственный аспект с помощью открытого конструктора, он выполнялся только один раз.
Ниже приведен мой фрагмент кода:
package com.akash.aop;
public class TestAopBefore {
public TestAopBefore() {
System.out.println("TestAopBefore.TestAopBefore()");
}
private String name;
public String getName() {
System.out.println("TestAopBefore.getName()");
return name;
}
public void setName(String name) {
System.out.println("TestAopBefore.setName()");
this.name = name;
}
}
Мой Аспект Класс
package com.akash.aop;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class MyAspect {
@Before("execution(* com.akash.aop.TestAopBefore.get*())")
public void runBeforeAllGetter() {
System.out.println("MyAspect.runBeforeAllGetter()");
}
}
Мой xml файл
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="testAopBefore" class="com.akash.aop.TestAopBefore" />
<bean id="myAspect" class="com.akash.aop.MyAspect" />
<aop:aspectj-autoproxy proxy-target-class="true" />
</beans>
Класс моего приложения
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
AbstractApplicationContext context = new ClassPathXmlApplicationContext(
"myAop.xml");
TestAopBefore testAopBefore = (TestAopBefore) context
.getBean("testAopBefore");
testAopBefore.setName("asd");
testAopBefore.getName();
}
}
Вот вывод:
TestAopBefore.TestAopBefore()
TestAopBefore.setName()
MyAspect.runBeforeAllGetter()
TestAopBefore.getName()
Редактировать:
Я использую проект Maven и вот мой pom.xml
<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>SpringDemo</groupId>
<artifactId>SpringDemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<org.springframework-version>4.0.3.RELEASE</org.springframework-version>
<org.aspectj-version>1.6.10</org.aspectj-version>
</properties>
<build>
<sourceDirectory>src</sourceDirectory>
<resources>
<resource>
<directory>resource</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework-version}</version>
<exclusions>
<!-- Exclude Commons Logging in favor of SLF4j -->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- AspectJ -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${org.springframework-version}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.5.8</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.5.8</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.5.8</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>
</dependencies>
</project>
Я также добавил зависимость для cglib, но я думаю, что мой код не использует его.
1 ответ
Я не совсем уверен, зачем вам дважды вызывать ваш конструктор, но если вам нужно объяснение, вот оно.
Начиная с версии Spring 4.0 DefaultAopProxyFactory использует ObjenesisCglibAopProxy, который создает экземпляр прокси, не вызывая конструктор по умолчанию для ваших классов. Поэтому, если вам нужно поведение двойного конструктора, вы должны перейти на Spring 3.x или создать собственную реализацию AopProxyFactory.
ура