前言

    Spring AOP的实现方法很多,在项目开发中具体采用什么方式,需要按实际情况来选择,每一种的用法,有其一定的实用价值,所以本文将各种使用方法进行了具体实现。主要包括Advice的before、after、throwing、around四种拦截方式的实现,如何进行正则匹配,自动化代理及AspectJ注解形式的实现。

AOP的定义

Spring AOP(Aspect-oriented programming) 面向切面编程,是一种特殊的拦截器,将一组程序中的公共部分抽离出来进行单独管理,降低程序的耦合度,aop和oo互为补充,面向对象编程将程序分解成各个层次的对象,而面向切面编程将程序运行过程分解成各个切面。也可以这样理解,面向对象编程是从静态角度考虑程序结构,面向切面编程是从动态角度考虑程序运行过程。

AOP中6个要素

(1)通知(增强)Advice

  通知定义了切面是什么以及何时使用,应该应用在某个方法被调用之前?之后?还是抛出异常时?等等。

(2)连接点 Join point

  连接点是在应用执行过程中能够插入切面的一个点。这个点可以是调用方法时,抛出异常时,甚至修改一个字段时。切面代码可以利用这些点插入到应用的正常流程中,并添加新的行为。

(3)切点 Pointcut

  切点有助于缩小切面所通知的连接点的范围。如果说通知定义了切面的“什么”和“何时”的话,那么切点就定义了“何处”,切点会匹配通知所要织入的一个或多个连接点,一般常用正则表达式

定义所匹配的类和方法名称来指定这些切点。

(4)切面 Aspect

  切面是通知和切点的结合。通知和切点定义了切面的全部内容——它是什么,在何时何处完成其功能。

(5)引入 Introduction

  引入允许我们向现有的类添加新方法或属性,从而无需修改这些现有类的情况下,让他们具有新的行为和状态。

(6)织入 Weaving

  在过去我常常把织入与引入的概念混淆,我是这样来辨别的,“引入”我把它看做是一个定义,也就是一个名词,而“织入”我把它看做是一个动作,一个动词,也就是切面在指定的连接点被织

入到目标对象中。

AOP用法总结

(1)Before advice 在方法执行前执行。

(2)After  returning  advice 在方法执行后返回一个结果后执行。

(3)After  throwing advice 在方法执行过程中抛出异常的时候执行。

(4)Around  advice 在方法执行前后和抛出异常时执行,相当于综合了以上三种通知。

(5)基于正则表达式,对符合匹配规则类或方法进行拦截处理。

(6)基于自动代理,简少配置。

(7)基于AspectJ注解形式,包括execution 表达式、@DeclareParents 注解、自动代理。

实例

1. Before advice 在方法执行前执行

创建Product产品类

 package com.jk.work.aopone;
/**
* Title: 产品
* Description: 该类的功能
*
* @author jihuan
* @create 2017-05-18
* @version: 1.0
*/
public class Product {
private String name;
private String type;
private int size; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getType() {
return type;
} public void setType(String type) {
this.type = type;
} public int getSize() {
return size;
} public void setSize(int size) {
this.size = size;
} public void printName(){
System.out.println("Product name "+ this.name);
} public void printType(){
System.out.println("Product type "+this.type);
} public void printThrowException(){
throw new IllegalArgumentException();
}
}

创建BeforeMethod类

 package com.jk.work.aopone;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
/**
* Title: BeforeMethod
* Description: 在方法执行前执行
*
* @author jihuan
* @create 2017-05-19
* @version: 1.0
*/
public class BeforeMethod implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("Before Method");
System.out.println("--------------------");
}
}

创建配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="product" class="com.jk.work.aopone.Product">
<property name="name" value="p2p p2p p2p" />
<property name="type" value="one year"/>
<property name="size" value="30000" />
</bean> <bean id="beforeMethodBean" class="com.jk.work.aopone.BeforeMethod" /> <bean id="productProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="product"/>
<property name="interceptorNames">
<list>
<value>beforeMethodBean</value>
</list>
</property>
<property name="proxyTargetClass" value="true"/> <!-- true 表 cglib,false 为jdkproxy(需要property 引入接口)-->
</bean>
</beans>

创建测试类Test.java

package com.jk.work.aopone;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Title: 类的主题(开发人员填写)
* Description: 该类的功能
*
* @author jihuan
* @create 2017-05-19
* @version: 1.0
*/
public class Test { public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/spring-aop.xml");
Product product = (Product) context.getBean("productProxy");
System.out.println("---------------------");
product.printName();
System.out.println("---------------------");
product.printType();
System.out.println("----------------------");
try{
product.printThrowException();
}catch(Exception e){
}
}
}

运行结果:

---------------------
Before Method
--------------------
Product name p2p p2p p2p
---------------------
Before Method
--------------------
Product type one year
----------------------
Before Method
--------------------

测试类可以采用编程式调用,简单实现:

package com.jk.work.aopone;
import org.springframework.aop.framework.ProxyFactory;
/**
* Title: 编程式
* Description: 该类的功能
*
* @author jihuan
* @create 2017-05-19 00:26
* @version: 1.0
*/
public class Test2 { public static void main(String[] args) {
ProxyFactory proxyFactory=new ProxyFactory() ;
Product product1=new Product();
product1.setName("p2p");
proxyFactory.setTarget(product1);
proxyFactory.addAdvice(new BeforeMethod());
Product product=(Product)proxyFactory.getProxy();
product.printName();
}
}

运行结果:

Before  Method
--------------------
Product name p2p

2.After  returning  advice 方法之后执行

创建AfterMethod类

 package com.jk.work.aopone;
import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;
/**
* Title: 类的主题(开发人员填写)
* Description: 该类的功能
*
* @author jihuan
* @create 2017-05-19 00:09
* @version: 1.0
*/
public class AfterMethod implements AfterReturningAdvice {
@Override
public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
System.out.println("-------------------");
System.out.println("After method ");
}
}

创建配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="product" class="com.jk.work.aopone.Product">
<property name="name" value="p2p p2p p2p" />
<property name="type" value="one year"/>
<property name="size" value="30000" />
</bean> <bean id="afterMethodBean" class="com.jk.work.aopone.AfterMethod" /> <bean id="productProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="product"/>
<property name="interceptorNames">
<list>
<value>afterMethodBean</value>
</list>
</property>
<property name="proxyTargetClass" value="true"/> <!-- true 表 cglib,false 为jdkproxy(需要property 引入接口)-->
</bean>
</beans> 

创建测试类复用Test.java

运行结果:

---------------------
Product name p2p p2p p2p
-------------------
After method
---------------------
Product type one year
-------------------
After method
----------------------

3. After  throwing advice 在方法执行过程中抛出异常的时候执行

创建ThrowException类

 package com.jk.work.aopone;
import org.springframework.aop.ThrowsAdvice;
/**
* Title: 类的主题(开发人员填写)
* Description: 该类的功能
*
* @author jihuan
* @create 2017-05-19
* @version: 1.0
*/
public class ThrowException implements ThrowsAdvice {
public void afterThrowing(IllegalArgumentException e) throws Throwable{
System.out.println("after Throwing Exception");
}
}

创建配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="product" class="com.jk.work.aopone.Product">
<property name="name" value="p2p p2p p2p" />
<property name="type" value="one year"/>
<property name="size" value="30000" />
</bean> <bean id="throwException" class="com.jk.work.aopone.ThrowException" /> <bean id="productProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="product"/>
<property name="interceptorNames">
<list>
<value>throwException</value>
</list>
</property>
<property name="proxyTargetClass" value="true"/> <!-- true 表 cglib,false 为jdkproxy(需要property 引入接口)-->
</bean>
</beans>

运行结果

---------------------
Product name p2p p2p p2p
---------------------
Product type one year
----------------------
after Throwing Exception

4. Around  advice 在方法执行前后和抛出异常时执行,相当于综合了以上三种通知 

创建AroundMethod类

 package com.jk.work.aopone;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import java.util.Arrays;
/**
* Title: 类的主题(开发人员填写)
* Description: 该类的功能
*
* @author jihuan
* @create 2017-05-19
* @version: 1.0
*/
public class AroundMethod implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("method name:" + methodInvocation.getMethod().getName());
System.out.println("method arguments" + Arrays.toString(methodInvocation.getArguments()));
System.out.println("Around method : before ");
try{
Object result = methodInvocation.proceed();
System.out.println("Around method : after ");
return result;
}catch(IllegalArgumentException e){
System.out.println("Around method : throw an exception ");
throw e;
}
}
}

创建配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="product" class="com.jk.work.aopone.Product">
<property name="name" value="p2p p2p p2p" />
<property name="type" value="one year"/>
<property name="size" value="30000" />
</bean> <bean id="aroundMethod" class="com.jk.work.aopone.AroundMethod" /> <bean id="productProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="product"/>
<property name="interceptorNames">
<list>
<value>aroundMethod</value>
</list>
</property>
<property name="proxyTargetClass" value="true"/> <!-- true 表 cglib,false 为jdkproxy(需要property 引入接口)-->
</bean>
</beans>

运行结果

---------------------
method name:printName
method arguments[]
Around method : before
Product name p2p p2p p2p
Around method : after
---------------------
method name:printType
method arguments[]
Around method : before
Product type one year
Around method : after
----------------------
method name:printThrowException
method arguments[]
Around method : before
Around method : throw an exception

5. 基于正则表达式的实现

采用RegexpMethodPointcutAdvisor来实现。采用的正则匹配规则,大概有四点,举例说明:

com\.service\..* 和 com\.service\..*Service\..* 和 .*get.* 和 .get.*

第一个表达式匹配的应该是com.service包下的所有方法
第二个表达式匹配的应该是com.service包下所有类名以Service结尾的所有方法
第三个表达式匹配的应该是所有类中含有get的方法
第四个表达式匹配的应该是所有类中以get为前缀的方法

具体如何实现,见下方实例:

创建Garden接口

 package com.jk.work.aoptwo;

 /**
* Created by jihuan on 17/5/20.
*/
public interface Garden { void fruitPlant(); void fruitGrow(); void fruitHarvest();
}

创建Garden实现类

 package com.jk.work.aoptwo;
/**
* Title: 类的主题(开发人员填写)
* Description: 该类的功能
*
* @author jihuan
* @create 2017-05-20
* @version: 1.0
*/
public class AppleGarden implements Garden{
@Override
public void fruitPlant() {
System.out.println("Apple plant...");
} @Override
public void fruitGrow() {
System.out.println("Apple grow...");
} @Override
public void fruitHarvest() {
System.out.println("Apple harvest...");
}
}

创建拦截类,采用MethodInterceptor,实现方法前后拦截

 package com.jk.work.aoptwo;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
/**
* Title: 类的主题(开发人员填写)
* Description: 该类的功能
*
* @author jihuan
* @create 2017-05-20
* @version: 1.0
*/
public class GardenAroundAdvice implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
before();
Object result=methodInvocation.proceed();
after();
return result;
}
private void before(){
System.out.println("before......");
}
private void after(){
System.out.println("after......");
}

创建配置文件,AppleGarden下所有以fruit开头的方法进行切面拦截

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <!--果园-->
<bean id="appleGarden" class="com.jk.work.aoptwo.AppleGarden" />
<bean id="gardenAroundAdvice" class="com.jk.work.aoptwo.GardenAroundAdvice" />
<bean id="gardenAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice" ref="gardenAroundAdvice" />
<property name="pattern" value="com.jk.work.aoptwo.AppleGarden.fruit.*" />
</bean> <bean id="productProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="appleGarden"/>
<property name="interceptorNames">
<list>
<value>gardenAdvisor</value>
</list>
</property>
<property name="proxyTargetClass" value="true"/> <!-- true 表 cglib,false 为jdkproxy(需要property 引入接口)-->
</bean>
</beans>

测试类

package com.jk.work.aoptwo;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Title: 类的主题(开发人员填写)
* Description: 该类的功能
*
* @author jihuan
* @create 2017-05-20
* @version: 1.0
*/
public class Test {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/spring-aop.xml");
AppleGarden appleGarden = (AppleGarden) context.getBean("productProxy");
System.out.println("----------1-----------");
appleGarden.fruitPlant();
System.out.println("----------2----------");
appleGarden.fruitGrow();
System.out.println("----------3-----------");
appleGarden.fruitHarvest(); }
}

运行效果:

----------1-----------
before......
Apple plant...
after......
----------2----------
before......
Apple grow...
after......
----------3-----------
before......
Apple harvest...
after...... Process finished with exit code 0

6. 基于自动代理的实现

采用自动代理的好处,可以减少配置,简化开发,spring的自动代理,采用了三种方式:

1)Advisor形式,实现类为DefaultAdvisorAutoProxyCreator;

2)Bean形式,实现类为BeanNameAutoProxyCreator;

3)AspjectJ注解形式,实现方式是@Aspect。

具体实例

 Advisor形式,实现类为DefaultAdvisorAutoProxyCreator

创建sprng-aop.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!--果园-->
<bean id="appleGarden" class="com.jk.work.aoptwo.AppleGarden" />
<bean id="gardenAroundAdvice" class="com.jk.work.aoptwo.GardenAroundAdvice" />
<bean id="gardenAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice" ref="gardenAroundAdvice" />
<property name="pattern" value="com.jk.work.aoptwo.AppleGarden.fruit.*" />
</bean>
<!--自动代理-->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
<property name="optimize" value="true"/><!-- true 自动寻找代理类,有接口,使用jdkproxy,否则采用cglib-->
</bean>
</beans>

测试类:

package com.jk.work.aoptwo;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Title: 类的主题(开发人员填写)
* Description: 该类的功能
*
* @author jihuan
* @create 2017-05-20
* @version: 1.0
*/
public class Test2 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/spring-aop.xml");
AppleGarden appleGarden = (AppleGarden) context.getBean("appleGarden");
System.out.println("----------1-----------");
appleGarden.fruitPlant();
System.out.println("----------2----------");
appleGarden.fruitGrow();
System.out.println("----------3-----------");
appleGarden.fruitHarvest();
}
}

运行效果

----------1-----------
before......
Apple plant...
after......
----------2----------
before......
Apple grow...
after......
----------3-----------
before......
Apple harvest...
after......

Bean形式,实现类为BeanNameAutoProxyCreator

创建spring-aop.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!--果园-->
<bean id="appleGarden" class="com.jk.work.aoptwo.AppleGarden" />
<bean id="gardenAroundAdvice" class="com.jk.work.aoptwo.GardenAroundAdvice" />
<bean id="gardenAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice" ref="gardenAroundAdvice" />
<property name="pattern" value="com.jk.work.aoptwo.AppleGarden.fruit.*" />
</bean> <!--自动代理-->
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames" value="*Garden" />
<property name="interceptorNames" value="gardenAdvisor"/>
<property name="optimize" value="true"/> <!--true 使用jdkproxy,false 采用cglib-->
</bean>
</beans>

测试类:

package com.jk.work.aoptwo;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Title: 类的主题(开发人员填写)
* Description: 该类的功能
*
* @author jihuan
* @create 2017-05-20
* @version: 1.0
*/
public class Test2 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/spring-aop.xml");
AppleGarden appleGarden = (AppleGarden) context.getBean("appleGarden");
System.out.println("----------1-----------");
appleGarden.fruitPlant();
System.out.println("----------2----------");
appleGarden.fruitGrow();
System.out.println("----------3-----------");
appleGarden.fruitHarvest();
}
}

运行效果

----------1-----------
before......
Apple plant...
after......
----------2----------
before......
Apple grow...
after......
----------3-----------
before......
Apple harvest...
after......

AspjectJ注解形式,实现类是AnnotationAwareAspectJAutoProxyCreator,在AspjectJ注解部分说明。

7. AspectJ注解

AspectJ注解方式,采用execution表达式进行切面拦截

创建spring-aop配置

<?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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="com.*"/>
<!--果园-->
<bean id="appleGarden" class="com.jk.work.aoptwo.AppleGarden" />
<bean id="gardenAroundAdvice" class="com.jk.work.aoptwo.GardenAroundAdvice" />
<bean id="gardenAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice" ref="gardenAroundAdvice" />
<property name="pattern" value="com.jk.work.aoptwo.AppleGarden.fruit.*" />
</bean>
<!--aspectj-->
<aop:aspectj-autoproxy proxy-target-class="true"/>
</beans>

创建AroundAspect 拦截类

 package com.jk.work.aoptwo;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component; /**
* Title: 类的主题(开发人员填写)
* Description: 该类的功能
*
* @author jihuan
* @create 2017-05-20
* @version: 1.0
*/
@Aspect
@Component
public class AroundAspect {
@Around("execution(* com.jk.work.aoptwo.AppleGarden.*(..))")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
handleBefore();
Object rs=proceedingJoinPoint.proceed();
handleAfter();
return rs;
} private void handleBefore(){
System.out.println("=====before=====");
}
private void handleAfter(){
System.out.println("=====after=====");
}
}

测试类

package com.jk.work.aoptwo;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Title: 类的主题(开发人员填写)
* Description: 该类的功能
*
* @author jihuan
* @create 2017-05-20
* @version: 1.0
*/
public class Test2 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/spring-aop.xml");
AppleGarden appleGarden = (AppleGarden) context.getBean("appleGarden");
System.out.println("----------1-----------");
appleGarden.fruitPlant();
System.out.println("----------2----------");
appleGarden.fruitGrow();
System.out.println("----------3-----------");
appleGarden.fruitHarvest();
}
}

运行效果

----------1-----------
=====before=====
Apple plant...
=====after=====
----------2----------
=====before=====
Apple grow...
=====after=====
----------3-----------
=====before=====
Apple harvest...
=====after=====

AspectJ @DeclareParents 注解,目标是对于一个已有的类引入新的接口,可以使用另一个接口类的功能,属于一种对类的扩展

创建新的接口Worker类

 package com.jk.work.aoptwo;

 /**
* Created by jihuan on 17/5/20.
*/
public interface Worker { void work(String task);

创建Worker的实现类

package com.jk.work.aoptwo;
/**
* Title: 类的主题(开发人员填写)
* Description: 该类的功能
*
* @author jihuan
* @create 2017-05-20 17:43
* @version: 1.0
*/
public class AppleWorker implements Worker{
@Override
public void work(String task) {
System.out.println("start work..."+task);
}
}

创建拦截器AroundAspect2

package com.jk.work.aoptwo;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;
import org.springframework.stereotype.Component; /**
* Title: 类的主题(开发人员填写)
* Description: 该类的功能
*
* @author jihuan
* @create 2017-05-20 17:40
* @version: 1.0
*/
@Aspect
@Component
public class AroundAspect2 {
@DeclareParents(value = "com.jk.work.aoptwo.AppleGarden",defaultImpl =AppleWorker.class )
private Worker worker;
}

spring-aop.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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="com.*"/>
<!--果园-->
<bean id="appleGarden" class="com.jk.work.aoptwo.AppleGarden" />
<bean id="gardenAroundAdvice" class="com.jk.work.aoptwo.GardenAroundAdvice" />
<bean id="gardenAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice" ref="gardenAroundAdvice" />
<property name="pattern" value="com.jk.work.aoptwo.AppleGarden.fruit.*" />
</bean>
<!--aspectj-->
<aop:aspectj-autoproxy proxy-target-class="true"/>
</beans>

创建测试类

package com.jk.work.aoptwo;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; /**
* Title: 类的主题(开发人员填写)
* Description: 该类的功能
*
* @author jihuan
* @create 2017-05-20 17:48
* @version: 1.0
*/
public class Test3 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/spring-aop.xml");
AppleGarden appleGarden = (AppleGarden) context.getBean("appleGarden");
Worker worker=(Worker)appleGarden;
System.out.println("----------1-----------");
worker.work("plant");
appleGarden.fruitPlant();
System.out.println("----------2----------");
worker.work("watering");
appleGarden.fruitGrow();
System.out.println("----------3-----------");
appleGarden.fruitHarvest();
worker.work("Harvest");
}
}

运行效果

----------1-----------
start work...plant
Apple plant...
----------2----------
start work...watering
Apple grow...
----------3-----------
Apple harvest...
start work...Harvest

 

AspjectJ注解自动代理方式的实现

创建拦截类

package com.jk.work.aoptwo;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
/**
* Title: 类的主题(开发人员填写)
* Description: 该类的功能
*
* @author jihuan
* @create 2017-05-20 17:21
* @version: 1.0
*/
@Aspect
@Component
public class AroundAspect {
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
handleBefore();
Object rs=proceedingJoinPoint.proceed();
handleAfter();
return rs;
} private void handleBefore(){
System.out.println("=====before=====");
}
private void handleAfter(){
System.out.println("=====after=====");
}
}

spring-aop.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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="com.*"/> <!--aspectj-->
<aop:config>
<aop:aspect ref="aroundAspect">
<aop:around method="around" pointcut="execution(* com.jk.work.aoptwo.AppleGarden.*(..))"/>
</aop:aspect>
</aop:config>
<aop:aspectj-autoproxy proxy-target-class="true"/>
</beans>

测试类

package com.jk.work.aoptwo;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Title: 类的主题(开发人员填写)
* Description: 该类的功能
*
* @author jihuan
* @create 2017-05-20 11:04
* @version: 1.0
*/
public class Test2 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/spring-aop.xml");
AppleGarden appleGarden = (AppleGarden) context.getBean("appleGarden");
System.out.println("----------1-----------");
appleGarden.fruitPlant();
System.out.println("----------2----------");
appleGarden.fruitGrow();
System.out.println("----------3-----------");
appleGarden.fruitHarvest();
}
}

运行效果

package com.jk.work.aoptwo;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Title: 类的主题(开发人员填写)
* Description: 该类的功能
*
* @author jihuan
* @create 2017-05-20 11:04
* @version: 1.0
*/
public class Test2 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/spring-aop.xml");
AppleGarden appleGarden = (AppleGarden) context.getBean("appleGarden");
System.out.println("----------1-----------");
appleGarden.fruitPlant();
System.out.println("----------2----------");
appleGarden.fruitGrow();
System.out.println("----------3-----------");
appleGarden.fruitHarvest();
}
}

总结

AOP的用法较多,熟悉每一种用法,能更好的在项目中发挥作用。AOP其实就是一种拦截器,底层采用JDKProxy动态代理和Cglib实现动态代理。对于有接口的形式采用JDKProxy加载处理目标对象。对于没有接口的普通类采用Cglib进行对象的拦截对出。JDKProxy的底层是java反射,Cglib的底层是调asm开源包。

如需转载,请标明本文作者:源码在深山,出处:博客园,原文链接:http://www.cnblogs.com/love-jk/p/spring-api.html

参考:

1) http://blog.csdn.net/topwqp/article/details/8695180

2)   http://www.cnblogs.com/zhaozihan/p/5953063.html

3)《轻量级Java EE企业应用实战》第三版

Spring-AOP用法总结的更多相关文章

  1. Java Spring AOP用法

    Java Spring AOP用法 Spring AOP Java web 环境搭建 Java web 项目搭建 Java Spring IOC用法 spring提供了两个核心功能,一个是IoC(控制 ...

  2. Spring AOP 用法浅谈(Day_18)

    当你这一天没有在进步,那你就是在退步! [简述] Aspect Oriented Programming :面向切面编程 所谓面向切面编程,是一种通过预编译和运行期动态代理的方式实现在不修改源代码的情 ...

  3. spring AOP的用法

    AOP,面向切面编程,它能把与核心业务逻辑无关的散落在各处并且重复的代码给封装起来,降低了模块之间的耦合度,便于维护.具体的应用场景有:日志,权限和事务管理这些方面.可以通过一张图来理解下: Spri ...

  4. 框架源码系列十:Spring AOP(AOP的核心概念回顾、Spring中AOP的用法、Spring AOP 源码学习)

    一.AOP的核心概念回顾 https://docs.spring.io/spring/docs/5.1.3.RELEASE/spring-framework-reference/core.html#a ...

  5. Spring AOP切点表达式用法总结

    1. 简介        面向对象编程,也称为OOP(即Object Oriented Programming)最大的优点在于能够将业务模块进行封装,从而达到功能复用的目的.通过面向对象编程,不同的模 ...

  6. Spring AOP 中@Pointcut的用法

    Spring Aop中@pointCut的用法,格式:execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? nam ...

  7. Spring AOP中JoinPoint的用法

    Spring JoinPoint的用法 JoinPoint 对象 JoinPoint对象封装了SpringAop中切面方法的信息,在切面方法中添加JoinPoint参数,就可以获取到封装了该方法信息的 ...

  8. 《Spring 5官方文档》 Spring AOP的经典用法

    原文链接 在本附录中,我们会讨论一些初级的Spring AOP接口,以及在Spring 1.2应用中所使用的AOP支持. 对于新的应用,我们推荐使用 Spring AOP 2.0来支持,在AOP章节有 ...

  9. 【spring AOP】@Pointcut的12种用法

    @Pointcut用来标注在方法上来定义切入点. 使用格式:@ 注解(value="表达标签 (表达式格式)").如:@Pointcut("execution(* com ...

  10. 转载:Spring AOP (上)

    工 作忙,时间紧,不过事情再多,学习是必须的.记得以前的部门老大说过:“开发人员不可能一天到晚只有工作,肯定是需要自我学习.第一:为了更充实自己,保 持进步状态.第二:为了提升技术,提高开发能力.第三 ...

随机推荐

  1. Unix环境编程基础下

    Unix出错处理 当UNIX系统的函数出错时,通常会返回一个负值.我们判断函数的返回值小于0表示出错了,注意我们并不知道为什么出错.例如我们open一个文件,返回值-1表示打开失败,但是为什么打开失败 ...

  2. [原]C#与非托管——封送和自动封送

    之前说到了如何从C函数声明通过简单的查找替换生成一份C#的静态引用声明(C#与非托管——初体验),因为只是简单说明,所以全部采用的是基础类型匹配和自动封送.自动封送虽然能省去我们不少编码时间,但如果不 ...

  3. ngrok把本地主机映射到公网域名

    这两天又要搞微信项目,然后我下载了一个QQ浏览器,搜索微信调试工具,我再搜,再搜,搜不出来,问了下客服,暂时下架了,好吧! 我上网搜了一下,就找到了  ngrok 这个东西,它也可以把你本地主机映射到 ...

  4. matlab函数:c2d离散化函数(待完善)

    Convert model from continuous to discrete time sysd =c2d(sys,Ts)sysd =c2d(sys,Ts,method)sysd =c2d(sy ...

  5. AngularJS进入使用前的准备工作

    安装 AngularJS是以JavaScript文件形式发布的,可以通过 script 标签添加到网页中. 下载地址:https://github.com/angular/angular.js/rel ...

  6. Java面试题04-final关键字详解

    Java面试题04-final关键字详解 本篇博客将会讨论java中final关键字的含义,以及final用在什么地方,感觉看书总会有一些模糊,而且解释的不是很清楚,在此做个总结,以备准备面试的时候查 ...

  7. 用jQuery模拟淘宝购物车

    首先我们要实现的内容的需求有如下几点: 1.在购物车页面中,当选中"全选"复选框时,所有商品前的复选框被选中,否则所有商品的复选框取消选中. 2.当所有商品前的复选框选中时,&qu ...

  8. node服务成长之路

    我们的系统也从第一代平台开始到现在第四代平台更换中,对这四代平台做一个简单的介绍: 第一代平台,主要是集中式,以快速上线为目的:第二代平台主要是分布式改造,缓解各服务压力:第三代平台主要做服务端SOA ...

  9. Azure WAF防火墙工作原理分析和配置向导

    Azure WAF工作原理分析和配置向导 本文博客地址为:http://www.cnblogs.com/taosha/p/6716434.html ,转载请保留出处,多谢! 本地数据中心往云端迁移的的 ...

  10. vue router-link 上添加点击事件

    在vue学习中遇到给router-link 标签添加事件@click .@mouseover等无效的情况 我想要做的是鼠标移上去出现删除标签,移除标签消失的效果 原代码: <router-lin ...