4、通知(Advice)
它定义在连接点做什么,为切面增强提供织入接口。例如,日志记录、权限验证、事务控制、性能检测、错误信息检测等。
Spring切面可以应用5种类型的通知:
前置通知(Before):在目标方法被调用之前调用通知功能;
后置通知(After):在目标方法完成之后调用通知,此时不会关心方法的输出是什么;
返回通知(After-returning):在目标方法成功执行之后调用通知;
异常通知(After-throwing):在目标方法抛出异常后调用通知;
环绕通知(Around):通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为。
5、通知器(Advisor)
完成对目标方法的切面增强设计和关注点的设计以后,需要一个对象把它们结合起来,完成这个作用的就是Advisor。
6、代理(Proxy)
它为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。
1、静态代理通常只代理一个类,动态代理是代理一个接口下的多个实现类。
2、静态代理事先知道要代理的是什么,而动态代理不知道要代理什么东西,只有在运行时才知道。
3、静态代理,在程序运行前,代理类的.class文件就已经存在了;动态代理,在程序运行时,运用反射机制动态创建而成。
1、举一个手机缴话费的例子,TelecomOperator 类是服务类。
package com.service;
/**
- 定义一个电信运营商接口
*/
public interface TelecomOperator {
//查询话费余额
public void queryPhoneBal();
//缴话费
public void payPhoneBal();
}
2、TelecomOperatorImpl是实现类
package com.controller;
import com.service.TelecomOperator;
public class TelecomOperatorImpl implements TelecomOperator {
//查询话费余额
@Override
public void queryPhoneBal(){
System.out.println(“查话费方法…”);
}
//缴话费
@Override
public void payPhoneBal(){
System.out.println(“缴话费方法…”);
}
}
3、TelecomOperatorProxy是服务代理类
package com.controller;
import com.service.TelecomOperator;
/**
-
第三方代理商
*/
public class TelecomOperatorProxy implements TelecomOperator {
private TelecomOperatorImpl telecomOperator;
public TelecomOperatorProxy(TelecomOperatorImpl telecomOperator) {
this.telecomOperator = telecomOperator;
}
//查询话费余额
@Override
public void queryPhoneBal(){
System.out.println(“切点:事务控制/日志输出”);
telecomOperator.queryPhoneBal();
System.out.println(“切点:事务控制/日志输出”);
}
//缴话费
@Override
public void payPhoneBal(){
System.out.println(“切点:事务控制/日志输出”);
telecomOperator.payPhoneBal();
System.out.println(“切点:事务控制/日志输出”);
}
}
4、TelecomOperatorTest是测试类
package com.controller;
public class TelecomOperatorTest {
public static void main(String[] args) {
TelecomOperatorImpl telecomOperator = new TelecomOperatorImpl();
TelecomOperatorProxy proxy = new TelecomOperatorProxy(telecomOperator);
proxy.queryPhoneBal();
proxy.payPhoneBal();
}
}
5、控制台输出
切点:事务控制/日志输出
查话费方法…
切点:事务控制/日志输出
切点:事务控制/日志输出
缴话费方法…
切点:事务控制/日志输出
1、JDK动态代理
package com.controller;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
- JDK动态代理类
*/
public class TelecomOperatorJDKProxy implements InvocationHandler {
private Object target;
//返回代理对象
public Object newProxy(Object target) {
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}
/**
-
@param obj 目标对象代理类的实例
-
@param method 代理实例上调用父类方法的Method实例
-
@param args 代入到代理实例上方法参数值的数组
*/
@Override
public Object invoke(Object obj, Method method, Object[] args) throws Throwable{
Object result = null;
System.out.println(“切点:事务控制/日志输出”);
result=method.invoke(target,args);
System.out.println(“切点:事务控制/日志输出”);
return result;
}
}
package com.controller;
import com.service.TelecomOperator;
public class TelecomOperatorJDKTest {
public static void main(String[] args) {
TelecomOperatorJDKProxy proxy = new TelecomOperatorJD
KProxy();
TelecomOperator telecomOperator = (TelecomOperator)proxy.newProxy(new TelecomOperatorImpl());
telecomOperator.queryPhoneBal();
}
}
控制台输出:
切点:事务控制/日志输出
查话费方法…
切点:事务控制/日志输出
2、Cglib动态代理
package com.controller;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
- Cglib动态代理类
*/
public class TelecomOperatorCglibProxy implements MethodInterceptor {
private Object target;//代理的目标对象
//创建目标对象的代理对象
public Object newProxy(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();//该类用于生成代理对象
enhancer.setSuperclass(this.target.getClass());//设置父类
enhancer.setCallback(this);//回调方法,设置回调对象为本身
return enhancer.create();//创建代理对象
}
/**
-
@param obj 目标对象代理类的实例(增强过)
-
@param method 代理实例上调用父类方法的Method实例
-
@param args 代入到代理实例上方法参数值的数组
-
@param proxy 使用它调用父类的方法
-
@throws Throwable
*/
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {