Concepts
Cross Cutting Concern: A isolated service, across all procedure in system
Aspect: The model pattern of Cross Cutting Point
Advice: The implementation of Aspect
Pointcut: Defines which JoinPoint(s) applied by Advice. For Spring, it's function invoke.
JoinPoint: the time point when Advice run, Spring only support JoinPoint on function
Weave: Apply Advice to Target Object called Weave. Spring support dynamic Weave.
Target Object: The Target Object that Advice applied to.
Proxy: Spring AOP default uses dynamic proxy from JDK, it's proxy is created when running. It can also use CGLIB proxy(when not using Interface).
Introduction: Add function for Class dynamically
See this first: Spring AOP
http://gvace.blogspot.com/2016/03/aop.html
To skip this and see: Spring AOP with AspectJ and Annotation
http://gvace.blogspot.com/2016/04/spring-aop-with-annotation.html
Example
Using Spring Version 4.2.5
Add dependency AspectJ
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>spring_static_proxy</groupId>
<artifactId>spring_static_proxy</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.build.mainClass>com.gvace.main</project.build.mainClass>
<java.version>1.7</java.version>
<spring.version>4.2.5.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.9</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
Create a class as Aspect
SecurityHandler.java
package com.gvace.aop;
/*
* To define an Aspect
*
*/
public class SecurityHandler {
private void checkSecurity() {
System.out.println("Runned checkSecurity");
}
}
An example interface(Target Object)
package com.gvace.inter;
public interface UserManager {
public void addUser(String username,String password);
public void delUser(int userId);
public String findUserById(int userId);
public void modifyUser(int userId, String username,String password);
}
The implementation of the interface(Target Object)
UserManagerImpl.java
package com.gvace.impl;
import com.gvace.inter.UserManager;
// each method have to call checkSecurity()
// and you don't want to change it based on requirement changes(like the codes being comment out)
public class UserManagerImpl implements UserManager {
@Override
public void addUser(String username, String password) {
//checkSecurity();
System.out.println("addUser:"+username+" "+password);
}
@Override
public void delUser(int userId) {
//checkSecurity();
System.out.println("delUser:"+userId+" ");
}
@Override
public String findUserById(int userId) {
//checkSecurity();
System.out.println("findUserById:"+userId+" ");
return "findUserById"+userId;
}
@Override
public void modifyUser(int userId, String username, String password) {
//checkSecurity();
System.out.println("modifyUser:"+userId+" "+username+" "+password);
}
/*
public void checkSecurity(){
System.out.println("Runned checkSecurity");
}
*/
}
Register beans and aspect annotation
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/aop/spring-tx.xsd">
<!-- Data Source -->
<bean id="userManager" class="com.gvace.impl.UserManagerImpl"></bean>
<!-- Aspect Class-->
<bean id="securityHandler" class="com.gvace.aop.SecurityHandler"></bean>
<aop:config>
<!-- Define Aspect, link to Aspect Class -->
<aop:aspect id="securityAspect" ref="securityHandler">
<!-- Define Pointcut -->
<aop:pointcut id="addAddMethod" expression="execution(* add*(..))"/>
<!-- Link the Advice method to Pointcut -->
<aop:before method="checkSecurity" pointcut-ref="addAddMethod"/>
</aop:aspect>
</aop:config>
</beans>
Test to run
Client.java
package com.gvace.test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.gvace.inter.UserManager;
public class Client {
public static void main(String[] args){
BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
UserManager userManager = (UserManager)factory.getBean("userManager");
//Since this UserManager interface contains function like execution(* add*(..))
//this userManager reference will not be the implementation class, it will be a Proxy
userManager.addUser("a", "b");
}
}
No comments:
Post a Comment