Spring-增强

Spring-增强

  AOP增强是指在目标类的连接点上织入一段代码。连接点由两个信息确定,一、方法表示的程序执行点;二、用相对点表示的方位。简单的来说,增强就是在目标类的方法执行前或者方法执行后拦截并加一段代码。一个类被AOP增强后,就产生了一个结果类,它是融合了原类和增强逻辑的代理类。

  Spring支持5种类型的增强,按照增强在目标类方法的连接点位置,可以分为以下5类:

  • BeforeAdvice(前置增强)

      BeforeAdvice类代表前置增强,因为Spring只支持方法级增强,所以MethodBeforeAdvice是目前可用的前置增强,表示在目标方法执行前实施增强。简单来说,就是在目标方法执行前拦截并执行一些代码。

  • AfterReturningAdvice(后置增强)

      AfterReturningAdvice代表后置增强,表示在目标方法执行后实施增强。简单来说,就是在目标方法执行后执行一些代码。

  • MethodInterceptor(环绕增强)

      MethodInterceptor代表环绕增强,表示在目标方法执行前后实施增强。简单来说,就是在目标方法执行前和后都会拦截并执行一些代码。

  • ThrowsAdvice(异常抛出增强)

      ThrowsAdvice代表抛出异常增强,表示在目标方法抛出异常后实施增强。简单来说,就是在目标方法抛出异常的时候拦截并执行一些代码。

  • IntroductionInterceptor(引介增强)

      IntroductionInterceptor代表引介增强,表示在目标类中添加一些新的方法和属性。

1.前置增强

  前置增强是在目标方法调用前执行,下面定义一个Cat类,里面有两个方法,分别为eatIng和eatEed。一只不可爱的猫的情况:

1
2
3
4
5
6
7
8
public class Cat {
public void eatIng(String name){
System.out.println(" I'm eating");
}
public void eatEed(String name){
System.out.println(" I'm finished");
}
}

闷不做声,毫无感情。下面通过增强来让这只猫显得可爱一些。


增强类

  MethodBeforeAdvice接口仅定义了唯一方法。method为目标类的方法;objects为目标类方法的入参;o为目标类实例。

1
2
3
4
5
6
7
8
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class Before implements MethodBeforeAdvice {//在目标类方法调用前执行
public void before(Method method, Object[] objects, Object o) throws Throwable {
String name=(String)objects[0];//获取方法第一个入参
System.out.print("瞄!瞄!瞄! I is "+name);
}
}

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
public class BeforeTest {
public static void main(String[] args) {
Cat c=new Cat();
BeforeAdvice advice=new Before();
ProxyFactory pf=new ProxyFactory();// Spring提供的代理工厂
pf.setTarget(c);//设置代理的目标
pf.addAdvice(advice);//为代理目标添加增强
Cat c1=(Cat)pf.getProxy();
System.out.println("我是Before增强");
c1.eatIng("旺财");
c1.eatEed("旺财");
}
}

下面通过xml配置声明一个代理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">

<!-- 需要代理的对象-->
<bean id="target" class="org.zmd.model.Cat"/>
<!--指定使用的增强-->
<bean id="before" class="org.zmd.Advice.Before"/>
<!--如果代理的对象实现了接口,需要用p:proxyInterfaces=""指定实现的接口-->
<bean id="c" class="org.springframework.aop.framework.ProxyFactoryBean"
p:interceptorNames="before"
p:target-ref="target"/>
</beans>

测试

1
2
3
4
5
6
7
8
9
10
public class BeforeTest1 {
public static void main(String[] args) {
String path="Advice/Before.xml";
ApplicationContext con=new ClassPathXmlApplicationContext(path);
Cat c= con.getBean("c",Cat.class);
System.out.println("我是Before增强");
c.eatIng("旺财");
c.eatEed("旺财");
}
}

上面两个测试的结果:


2.后置增强

  后置增强是在目标类方法调用后执行。下面通过后置增强让猫显得更加可爱。

增强类

  通过实现AfterReturningAdvice接口来定义增强的逻辑。o为目标实例方法返回的结果;method为目标类方法;objects为目标实例的方法的入参;o1为目标类实例。

1
2
3
4
5
6
7
import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;
public class After implements AfterReturningAdvice {
public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
System.out.println("瞄!瞄!瞄! 谢谢老板的饭。");
}
}

测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class AfterTest {
public static void main(String[] args) {
Cat c=new Cat();
BeforeAdvice before=new Before();
AfterReturningAdvice aftet=new After();
ProxyFactory pf =new ProxyFactory();
pf.setTarget(c);//设置代理的对象
pf.addAdvice(before);//添加前置增强
pf.addAdvice(aftet);//添加后置增强
Cat c1=(Cat) pf.getProxy();
System.out.println("我是After增强");
c1.eatIng("旺财");
c1.eatEed("旺财");
}
}

XML配置

1
2
3
4
5
6
7
8
9
10
11
12
<?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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="target" class="org.zmd.model.Cat"/>
<bean id="after" class="org.zmd.Advice.After"/>
<bean id="before" class="org.zmd.Advice.Before"/>
<bean id="c" class="org.springframework.aop.framework.ProxyFactoryBean"
p:target-ref="target"
p:interceptorNames="after,before"/>
</beans>

测试结果:


3.环绕增强

  环绕增强的作用已经很明显了,环绕增强允许在目标类方法调用前后织入横切逻辑,它综合实现了前置、后置增强两者的功能。

增强类

1
2
3
4
5
6
7
8
9
10
11
12
13
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class Interceptor implements MethodInterceptor {
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
Object [] o=methodInvocation.getArguments();
String name=(String)o[0];
System.out.print("瞄!瞄!瞄! I is "+name);//目标方法执行前调用
Object ob=methodInvocation.proceed();//通过反射机制调用目标方法
System.out.println("瞄!瞄!瞄! 谢谢老板的饭。");//目标方法执行后调用
return ob;
}
}

XML配置

1
2
3
4
5
6
7
8
9
10
11
<?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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="target" class="org.zmd.model.Cat"/>
<bean id="in" class="org.zmd.Advice.Interceptor"/>
<bean id="c" class="org.springframework.aop.framework.ProxyFactoryBean"
p:interceptorNames="in"
p:target-ref="target"/>
</beans>

测试:


4.异常抛出增强

  定义Dog类,里面有两个抛出异常的方法。

1
2
3
4
5
6
7
8
9
10
11
import java.sql.SQLException;
public class Dog {

public void Hungry(String name) throws Exception{
throw new SQLException("我饿得都不认识你了!铲屎官");
}

public void Bad(String name){
throw new RuntimeException("我生病了!铲屎官!");
}
}

增强类

1
2
3
4
5
6
7
8
9
10
import org.springframework.aop.ThrowsAdvice;
import java.lang.reflect.Method;
public class Throw implements ThrowsAdvice {
public void afterThrowing(Method method,Object [] args,Object target,Exception ex) throws Throwable{
System.out.println("**************");
System.out.println("函数名:"+method.getName());
System.out.println("抛出异常: 我是"+args[0]+" "+ex.getMessage());
System.out.println("成功增强异常");
}
}

测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class ThrowTest {
public static void main(String[] args) {
Dog d=new Dog();
ProxyFactory pf=new ProxyFactory();
ThrowsAdvice t=new Throw();
pf.setTarget(d);
pf.addAdvice(t);
Dog d1=(Dog) pf.getProxy();
try {
d1.Hungry("广生");
} catch (Exception e) {
e.printStackTrace();
}
d1.Bad("广生");
}
}

结果:


  

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×