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
Then see this Spring AOP with AspectJ with no Annotation Config
http://gvace.blogspot.com/2016/04/spring-aop-with-aspectj-no-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; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; /* * To define an Aspect * */ @Aspect public class SecurityHandler { //@Pointcut Describe the target functions //So this function is ONLY JUST A FLAG, it will NEVER be called anyway //(* add*(..)), means return any type, name likes "add*", parameter can be anything // the addAddMethod function does not want parameter and return type @Pointcut("execution(* add*(..))") private void addAddMethod(){} //define this Advice is run before target function //And it applied to some @Pointcut described functions @Before(value = "addAddMethod()") //@After(value = "addAddMethod()") 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"> <!-- Enable AspectJ Annotation --> <aop:aspectj-autoproxy/> <!-- Data Source --> <bean id="userManager" class="com.gvace.impl.UserManagerImpl"></bean> <!-- Aspect --> <bean id="securityHandler" class="com.gvace.aop.SecurityHandler"></bean> </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