
Aspect Orieted Programming面向切面(方面)编程。
是一种编程模式,将分布在多个类中的功能封装到一个类中,这些功能称为cross-cutting concerns (横切关注点),如日志,事务,缓存,安全等等。
不是替代OOP,而是对其的补充。
减少了大量的代码重复。
功能组件之间的解耦。
常见AOP框架
AspectJ、Spring、Aspectwerkz、JBoss AOP...
AOP的类型静态AOP
修改应用程序的字节码,必要时会改变与扩展应用程序代码。
性能好,但是改动了切面需要重新编译整个应用程序。
AspectJ提供了实现。
动态AOP
实现过程是在运行时动态执行的。
性能稍差,但改动了切面无需重新编译整个应用程序。
Spring使用代理机制实现。
概念
说明
Advice,通知
需要单独封装的功能,定义在类的方法中。
JoinPoint,连接点
可以使用通知的地方。
PointCut,切入点
定义使用通知的连接点集合。
Aspect,切面
通知和切入点的组合。
Advisor,切面
通知和切入点的组合。
Weaving,织入
把切面应用到应用程序中的过程。
Target,目标
应用切面的对象。
Introduction,引入
向现有的类添加新方法或新属性。
实现机制
代理Bean使用ProxyFactory产生。
内部根据情况使用不同的代理实现。
代理Bean注入到调用者中供使用。
两种代理实现
连接点类型
Spring只支持一种连接点类型:方法调用。
可以继承AspectJ提供更多类型的连接点支持。
通知类型
通知类型
说明
Before通知
方法调用之前执行。
可以访问调用方法的目标,方法及参数,但不能控制方法本身的执行。
如果通知抛出异常,通知链后续的通知及方法本身都不会执行。
Around通知
在方法调用之前和之后执行。
可以改变方法的执行逻辑。
After通知
AfterReturning通知
方法调用且返回结果后执行。
可以访问调用方法的目标,方法,参数及返回值,但不能控制方法本身的执行。
如果目标方法抛出异常,通知不会执行。
Throws通知
方法调用返回后执行,但是方法要抛出异常才会执行,一般用于处理特定的异常。
必须实现特定的方法(不是接口声明的)afterThrowing(...)
编写通知类,该类实现通知对应的接口。
使用ProxyFactory提供的方法设置目标及通知对象。
使用ProxyFactory获取目标的代理。
构造方法
new ProxyFactory()
new ProxyFactory(Object target)
new ProxyFactory(Class>... proxyInterfaces)
new ProxyFactory(Class> proxyInterfaces, Interceptor interceptor)
new ProxyFactory(Class> proxyInterfaces, TargetSource targetSource)
普通方法
addAdvice()/removeAdvice()
增加/移除Advice到/从通知链。
setTarget()/setTargetClass()
设置目标对象。
addInterface()/setInterfaces()
增加/设置目标类的接口。
getProxy()
创建并返回代理对象。
adviceIncluded()
判断Advice是否存在于通知链中。
addAdvisor()/addAdvisors/removeAdvisor()
增加/移除Advisor到/从通知链。
通知对应的接口
Before
org.springframework.aop.MethodBeforeAdvice
AfterReturing
org.springframework.aop.AfterReturningAdvice
After
org.springframework.aop.AfterAdvice
Around
org.aopalliance.intercept.MethodInteceptor
Throws
org.springframework.aop.ThrowsAdvice
Introduction
org.springframework.aop.IntroductionInterceptor
public class MyAdvice {
public static void main(String[] args) {
Target target = new Target();
MyBeforeAdvice myBeforeAdvice = new MyBeforeAdvice();
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(target);
proxyFactory.addAdvice(myBeforeAdvice);
Target proxy = (Target)proxyFactory.getProxy();
proxy.method();
}
}
class MyBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("MyBeforeAdvice...");
}
}
class Target {
public void method() {
System.out.println("target method...执行...");
}
}
afternReturning通知MyBeforeAdvice...
target method...执行...
public class MyAdvice {
public static void main(String[] args) {
Target target = new Target();
MyAfterReturningAdvice myAfterReturningAdvice = new MyAfterReturningAdvice();
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(target);
proxyFactory.addAdvice(myAfterReturningAdvice);
Target proxy = (Target)proxyFactory.getProxy();
proxy.method();
}
}
class MyAfterReturningAdvice implements AfterReturningAdvice {
@Override
public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
System.out.println("MyAfterReturningAdvice...执行结果 " + o);
}
}
class Target {
public String method() {
System.out.println("target method1...执行...");
return "myAfterReturningAdvice执行结果...";
}
}
Around通知target method1...执行...
MyAfterReturningAdvice...执行结果 myAfterReturningAdvice执行结果...
public class MyAdvice {
public static void main(String[] args) {
Target target = new Target();
MyAroundAdvice myAroundAdvice = new MyAroundAdvice();
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(target);
proxyFactory.addAdvice(myAroundAdvice);
Target proxy = (Target)proxyFactory.getProxy();
proxy.method();
}
}
class MyAroundAdvice implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("MyAroundAdvice start...");
Object result = methodInvocation.proceed();
System.out.println("方法执行结束..." + result);
System.out.println("MyAroundAdvice end...");
return null;
}
}
class Target {
public String method() {
System.out.println("target method...执行...");
return "MyAroundAdvice执行结果...";
}
}
throws通知MyAroundAdvice start...
target method...执行...
方法执行结束...MyAroundAdvice执行结果...
MyAroundAdvice end...
throwsAdvice方法调用返回后执行,但是方法要抛出异常才会执行,一般用于处理特定的异常。
必须实现特定的方法(不是接口声明的)。
public class MyAdvice {
public static void main(String[] args) {
Target target = new Target();
MyThrowsAdvice myThrowsAdvice = new MyThrowsAdvice();
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(target);
proxyFactory.addAdvice(myThrowsAdvice);
Target proxy = (Target)proxyFactory.getProxy();
try {
proxy.method();
} catch (Exception e) {
//e.printStackTrace();
}
}
}
class Target {
public void method() throws Exception{
System.out.println("target method...执行...");
throw new Exception("method error...");
}
}
注意:实现ThrowsAdvice接口的类必须是public修饰
public class MyThrowsAdvice implements ThrowsAdvice {
public void afterThrowing(Method method, Object[] args, Object target, Exception ex) {
System.out.println("MyThrowsAdvice异常: " + ex.getMessage());
}
}
增加/设置目标类接口target method...执行...
MyThrowsAdvice异常: method error...
public class MyAdvice {
public static void main(String[] args) {
Target target = new Target();
MyBeforeAdvice myBeforeAdvice = new MyBeforeAdvice();
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(target);
//proxyFactory.setInterfaces(ITarget.class);
proxyFactory.addAdvice(myBeforeAdvice);
//ITarget proxy = (ITarget)proxyFactory.getProxy();
Target proxy = (Target) proxyFactory.getProxy();
System.out.println(proxy);
proxy.method();
}
}
class MyBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("MyBeforeAdvice... ");
}
}
class Target implements ITarget{
public void method(){
System.out.println("before");
}
}
interface ITarget{
void method();
}
Pointcut接口MyBeforeAdvice...
org.crazy.aop.Target@6b71769e
MyBeforeAdvice...
before
使用advice通知时,在方法调用时都会使用相关定义的通知,某些非必要的方法就不需要通知如toString(),此时就需要切入点,指定具体哪些方法需要通知。
该接口表示切入点
ClassFilter getClassFileter()
ClassFilter接口,用于匹配切入点或引入的目标类。
MethodMatcher getMethodMatcher()
MethodMatcher接口:用于匹配方法是否是合适的切入点以便应用切面。
MethodMatcher接口的实现支持静态与动态两种类型,取决于首先调用法isRuntime()的返回值。
返回true
动态,先调用一次matches(Method m, Class> targetClass)方法,若该方法返回true,则后续调用matches(Method m, Class> targetClass, Object[] args)方法。
返回false
静态,只调用一次matches(Method m, Class> targetClass)方法。
检查切入点时,首先调用getClassFileter()方法检查目标类是否匹配,若返回true,再调用getMethodMatcher()检查方法是否匹配。
Spring提供了若干Pointcut的实现类
StaticMethodMatcherPointcut
实现静态MethodMatcher的抽象类。
重写其matches(Method method, @Nullable Class> targetClass)实现逻辑。
JdkRegexpMethodPointcut
使用Jdk的正则表达式匹配。
NameMatchMethodPointcut
使用方法名的简单匹配。
DynamicMethodMatchetPointcut
实现动态MethodMatcher的抽象类。
重写其matches(Method method, Class> targetClass, Object... args)实现逻辑。
AnnotationMatchingPointcut
用于匹配特定注解修饰的类或方法。
AspectJexpressionPointcut
使用AspectJ表达式作为切入规则;
需要AspectJ支持。
ComposablePointcut
用于 *** 作多个Pointcut。
ControlFlowPointcut
切面应用于从指定类中调用的方法。
public class MyAdvice {
public static void main(String[] args) {
Target target = new Target();
MyBeforeAdvice myBeforeAdvice = new MyBeforeAdvice();
ProxyFactory proxyFactory = new ProxyFactory();
Pointcut pointcut = new StaticMethodMatcherPointcut() {
@Override
public boolean matches(Method method, Class> aClass) {
return "method2".equals(method.getName());
}
};
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut,myBeforeAdvice);
proxyFactory.setTarget(target);
proxyFactory.addAdvisor(advisor);
Target proxy = (Target)proxyFactory.getProxy();
proxy.method1();
proxy.method2();
}
}
class MyBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("MyBeforeAdvice... ");
}
}
class Target {
public void method1(){
System.out.println("Target method1() running...");
}
public void method2(){
System.out.println("Target method2() running...");
}
}
DynamicMethodMatchetPointcutTarget method1() running...
MyBeforeAdvice...
Target method2() running...
public class MyAdvice {
public static void main(String[] args) {
Target target = new Target();
MyBeforeAdvice myBeforeAdvice = new MyBeforeAdvice();
ProxyFactory proxyFactory = new ProxyFactory();
Pointcut pointcut = new DynamicMethodMatcherPointcut() {
@Override
public boolean matches(Method method, Class> aClass, Object... objects) {
return "method1".equals(method.getName()) && objects.length > 0 && objects[0].equals("one");
}
};
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut,myBeforeAdvice);
proxyFactory.setTarget(target);
proxyFactory.addAdvisor(advisor);
Target proxy = (Target)proxyFactory.getProxy();
proxy.method1();
proxy.method1("one");
proxy.method2();
}
}
class MyBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("MyBeforeAdvice... ");
}
}
class Target {
public void method1(){
System.out.println("Target method1() running...");
}
public void method1(String str){
System.out.println("Target method1(String) running...");
}
public void method2(){
System.out.println("Target method2() running...");
}
}
JdkRegexpMethodPointcutTarget method1() running...
MyBeforeAdvice...
Target method1(String) running...
Target method2() running...
public class MyAdvice {
public static void main(String[] args) {
Target target = new Target();
MyBeforeAdvice myBeforeAdvice = new MyBeforeAdvice();
ProxyFactory proxyFactory = new ProxyFactory();
JdkRegexpMethodPointcut pointcut = new JdkRegexpMethodPointcut();
pointcut.setPattern(".*method1.*");
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut,myBeforeAdvice);
proxyFactory.setTarget(target);
proxyFactory.addAdvisor(advisor);
Target proxy = (Target)proxyFactory.getProxy();
proxy.method1();
proxy.method1("one");
proxy.method2();
}
}
class MyBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("MyBeforeAdvice... ");
}
}
class Target {
public void method1(){
System.out.println("Target method1() running...");
}
public void method1(String str){
System.out.println("Target method1(String) running...");
}
public void method2(){
System.out.println("Target method2() running...");
}
}
NameMatchMethodPointcutMyBeforeAdvice...
Target method1() running...
MyBeforeAdvice...
Target method1(String) running...
Target method2() running...
public class MyAdvice {
public static void main(String[] args) {
Target target = new Target();
MyBeforeAdvice myBeforeAdvice = new MyBeforeAdvice();
ProxyFactory proxyFactory = new ProxyFactory();
NameMatchMethodPointcut pointcut = new NameMatchMethodPointcut();
pointcut.addMethodName("method1");
pointcut.setMappedName("method2");
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut,myBeforeAdvice);
proxyFactory.setTarget(target);
proxyFactory.addAdvisor(advisor);
Target proxy = (Target)proxyFactory.getProxy();
proxy.method1();
proxy.method1("one");
proxy.method2();
}
}
class MyBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("MyBeforeAdvice... ");
}
}
class Target {
public void method1(){
System.out.println("Target method1() running...");
}
public void method1(String str){
System.out.println("Target method1(String) running...");
}
public void method2(){
System.out.println("Target method2() running...");
}
}
AnnotationMatchingPointcutTarget method1() running...
Target method1(String) running...
MyBeforeAdvice...
Target method2() running...
public class MyAdvice {
public static void main(String[] args) {
Target target = new Target();
MyBeforeAdvice myBeforeAdvice = new MyBeforeAdvice();
ProxyFactory proxyFactory = new ProxyFactory();
//AnnotationMatchingPointcut pointcut = new AnnotationMatchingPointcut(MyAnnotation.class);
AnnotationMatchingPointcut pointcut = AnnotationMatchingPointcut.forMethodAnnotation(MyAnnotation.class);
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut,myBeforeAdvice);
proxyFactory.setTarget(target);
proxyFactory.addAdvisor(advisor);
Target proxy = (Target)proxyFactory.getProxy();
proxy.method1();
proxy.method1("one");
proxy.method2();
}
}
class MyBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("MyBeforeAdvice... ");
}
}
@MyAnnotation
class Target {
public void method1(){
System.out.println("Target method1() running...");
}
public void method1(String str){
System.out.println("Target method1(String) running...");
}
public void method2(){
System.out.println("Target method2() running...");
}
}
@Retention(RetentionPolicy.RUNTIME)
@java.lang.annotation.Target({ElementType.TYPE,ElementType.METHOD})
@interface MyAnnotation {
}
AspectJexpressionPointcutTarget method1() running...
Target method1(String) running...
Target method2() running...
public class MyAdvice {
public static void main(String[] args) {
Target target = new Target();
MyBeforeAdvice myBeforeAdvice = new MyBeforeAdvice();
ProxyFactory proxyFactory = new ProxyFactory();
AspectJexpressionPointcut pointcut = new AspectJexpressionPointcut();
pointcut.setexpression("execution(* method*(..))");
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut,myBeforeAdvice);
proxyFactory.setTarget(target);
proxyFactory.addAdvisor(advisor);
Target proxy = (Target)proxyFactory.getProxy();
proxy.method1();
proxy.method1("one");
proxy.method2();
}
}
class MyBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("MyBeforeAdvice... ");
}
}
class Target {
public void method1(){
System.out.println("Target method1() running...");
}
public void method1(String str){
System.out.println("Target method1(String) running...");
}
public void method2(){
System.out.println("Target method2() running...");
}
}
ComposablePointcutMyBeforeAdvice...
Target method1() running...
MyBeforeAdvice...
Target method1(String) running...
MyBeforeAdvice...
Target method2() running...
public class MyAdvice {
public static void main(String[] args) {
Target target = new Target();
MyBeforeAdvice myBeforeAdvice = new MyBeforeAdvice();
ProxyFactory proxyFactory = new ProxyFactory();
AspectJexpressionPointcut pointcut = new AspectJexpressionPointcut();
pointcut.setexpression("execution(* method1*(..))");
AnnotationMatchingPointcut pointcut1 = AnnotationMatchingPointcut.forMethodAnnotation(MyAnnotation.class);
ComposablePointcut pointcut2 = new ComposablePointcut((Pointcut)pointcut);
pointcut2.intersection(pointcut1);
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut,myBeforeAdvice);
proxyFactory.setTarget(target);
proxyFactory.addAdvisor(advisor);
Target proxy = (Target)proxyFactory.getProxy();
proxy.method1();
proxy.method1("one");
proxy.method2();
}
}
class MyBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("MyBeforeAdvice... ");
}
}
@MyAnnotation
class Target {
public void method1(){
System.out.println("Target method1() running...");
}
@MyAnnotation
public void method1(String str){
System.out.println("Target method1(String) running...");
}
public void method2(){
System.out.println("Target method2() running...");
}
}
@Retention(RetentionPolicy.RUNTIME)
@java.lang.annotation.Target({ElementType.TYPE,ElementType.METHOD})
@interface MyAnnotation {
}
ControlFlowPointcutMyBeforeAdvice...
Target method1() running...
MyBeforeAdvice...
Target method1(String) running...
Target method2() running...
public class MyAdvice {
public static void main(String[] args) {
Target target = new Target();
MyBeforeAdvice myBeforeAdvice = new MyBeforeAdvice();
ProxyFactory proxyFactory = new ProxyFactory();
ControlFlowPointcut pointcut = new ControlFlowPointcut(Service.class, "doService");
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut,myBeforeAdvice);
proxyFactory.setTarget(target);
proxyFactory.addAdvisor(advisor);
Target proxy = (Target)proxyFactory.getProxy();
proxy.method1();
proxy.method1("one");
proxy.method2();
new Service().doService(proxy);
}
}
class MyBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("MyBeforeAdvice... ");
}
}
class Target {
public void method1(){
System.out.println("Target method1() running...");
}
public void method1(String str){
System.out.println("Target method1(String) running...");
}
public void method2(){
System.out.println("Target method2() running...");
}
}
class Service{
public void doService(Target target) {
target.method1();
}
}
Target method1() running...
Target method1(String) running...
Target method2() running...
MyBeforeAdvice...
Target method1() running...
Advisor接口
该接口表示切面,有两个子接口:
PointcutAdvisor
DefaultPointcutAdvisor是PointcutAdvisor的默认实现。
NameMatchMethodPointcutAdvisor
RegexpMethodPointcutAdvisor
AspectJPointcutAdvisor
IntroductionAdvisor
Pointcus类:
该类提供了两个常量及若干工具方法。
常量
SETTERS: 匹配set方法的Pointcut
GETTERS: 匹配get方法的Pointcut
方法
Pointcut union(Pointcut pc1, Pointcut pc2)
Pointcut intersection(Pointcut pc1, Pointcut pc2)
Introduction引入:
Introduction,可以在不改变目标对象的情况下动态引入新功能到已存在的对象上。
新功能使用实现了某个接口的类进行封装。
实际上是一个特殊类型的Around(环绕)通知。
只用于类级别上。
引入的实现方式:
声明接口
定义需要引入实现的方法;
声明引入
实现自定义的接口及IntroductionInterceptor接口(通常继承该接口的实现类DelegatingIntroductionInterceptor);
使用引入
直接将其作为Advice增加到ProxyFactory中。
实现IntroductionAdvisor接口,通常继承实现类DefaultIntroductionAdvosor,将引入作为参数传递给其构造方法,同时提供可选的IntroductionInfo限定类型,然后将其作为Advisor增加到ProxyFactory中。
实现方式一:
public class IntroductionTest {
public static void main(String[] args) {
Watch watch = new Watch();
MyCallWatch myCallWatch = new MyCallWatch();
ProxyFactory factory = new ProxyFactory();
factory.setTarget(watch);
factory.addAdvice(myCallWatch);
factory.setOptimize(true);//
Watch w1 =(Watch)factory.getProxy();
w1.showTime();
CallWatch w2 = (CallWatch)w1;//将代理对象转换成合适的接口类型
w2.call();
}
}
class Watch {
public void showTime() {
System.out.println("My watch can showTime...");
}
}
interface CallWatch {
void call();
}
class MyCallWatch extends DelegatingIntroductionInterceptor implements CallWatch {
@Override
public void call() {
System.out.println("My watch can call phone...");
}
}
My watch can showTime...
My watch can call phone...
实现方式二:
public static void main(String[] args) {
Watch watch = new Watch();
MyCallWatch myCallWatch = new MyCallWatch();
ProxyFactory factory = new ProxyFactory();
factory.setTarget(watch);
factory.addAdvisor(new MyNewFunctionAdvisor(myCallWatch));
factory.setOptimize(true);//
Watch w1 =(Watch)factory.getProxy();
w1.showTime();
CallWatch w2 = (CallWatch)w1;//将代理对象转换成合适的接口类型
w2.call();
RecordSport w3 = (RecordSport)w1;
w3.recordSport();
}
}
class Watch {
public void showTime() {
System.out.println("My watch can showTime...");
}
}
interface CallWatch {
void call();
}
interface RecordSport {
void recordSport();
}
class MyCallWatch extends DelegatingIntroductionInterceptor implements CallWatch, RecordSport {
@Override
public void call() {
System.out.println("My watch can call phone...");
}
@Override
public void recordSport() {
System.out.println("My watch can record sports...");
}
}
class MyNewFunctionAdvisor extends DefaultIntroductionAdvisor {
public MyNewFunctionAdvisor(Advice advice) {
super(advice, new IntroductionInfo() {
@Override
public Class>[] getInterfaces() {
return new Class[] {CallWatch.class, RecordSport.class};
}
});
}
}
My watch can showTime...
My watch can call phone...
My watch can record sports...
ProcxyFactory
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)