Spring注解-(十三)SpringAOP的使用方式

本文最后更新于:June 15, 2022 pm

Spring 是目前主流的 Java Web 开发框架,是 Java 世界最为成功的框架。Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。该框架是一个轻量级的开源框架,具有很高的凝聚力和吸引力。Spring 框架不局限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何 Java 应用都可以从 Spring 中受益。Spring 框架还是一个超级粘合平台,除了自己提供功能外,还提供粘合其他技术和框架的能力。

目录

ProxyFactory

目标类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.SpringTestAnnotation.TestValue;

import org.springframework.stereotype.Component;

/**
* @Author DragonOne
* @Date 2022/6/10 21:56
* @墨水记忆 www.tothefor.com
*/
@Component
public class OrderS {

}

使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.SpringTestAnnotation.TestValue;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
* @Author DragonOne
* @Date 2022/6/10 11:16
* @墨水记忆 www.tothefor.com
*/
@Component
public class Per {

@Autowired
private OrderS orderS;

public void show(){
System.out.println("Per show "+orderS);
}

}

测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package com.SpringTestAnnotation;

import com.SpringTestAnnotation.TestValue.Per;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
* @Author DragonOne
* @Date 2022/6/10 11:16
* @墨水记忆 www.tothefor.com
*/
public class TestAnnotation {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TestConfig.class);

Per per = new Per();
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(per);

proxyFactory.addAdvice(new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("before dong");
Object proceed = invocation.proceed();
System.out.println("after dong");
return proceed;
}
});

Per proxy = (Per) proxyFactory.getProxy();
proxy.show();


}
}

addAdvice就表示代理逻辑。

输出结果:

1
2
3
before dong
Per show null
after dong

ProxyFactoryBean

相同代码不写,同上。

配置类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.SpringTestAnnotation;

import com.SpringTestAnnotation.TestValue.Per;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;

/**
* @Author DragonOne
* @Date 2022/6/10 11:16
* @墨水记忆 www.tothefor.com
*/
@ComponentScan(value = "com.SpringTestAnnotation")
public class TestConfig {

@Bean
public ProxyFactoryBean perProxy(){
Per per = new Per();
ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
proxyFactoryBean.setTarget(per);
proxyFactoryBean.addAdvice(new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("before dong");
Object proceed = invocation.proceed();
System.out.println("after dong");
return proceed;
}
});
return proxyFactoryBean;
}

}

测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.SpringTestAnnotation;

import com.SpringTestAnnotation.TestValue.Per;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
* @Author DragonOne
* @Date 2022/6/10 11:16
* @墨水记忆 www.tothefor.com
*/
public class TestAnnotation {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TestConfig.class);

Per orderS = (Per) applicationContext.getBean("perProxy");
orderS.show();

}
}

输出结果:

1
2
3
before dong
Per show null
after dong

BeanNameAutoProxyCreator

配置类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package com.SpringTestAnnotation;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;

/**
* @Author DragonOne
* @Date 2022/6/10 11:16
* @墨水记忆 www.tothefor.com
*/
@ComponentScan(value = "com.SpringTestAnnotation")
public class TestConfig {

@Bean
public MethodInterceptor totheforAdvice(){

return new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("before dong");
Object proceed = invocation.proceed();
System.out.println("after dong");
return proceed;
}
};
}

@Bean
public BeanNameAutoProxyCreator beanNameAutoProxyCreator(){
BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();
beanNameAutoProxyCreator.setBeanNames("per*");
beanNameAutoProxyCreator.setInterceptorNames("totheforAdvice");
beanNameAutoProxyCreator.setProxyTargetClass(true);

return beanNameAutoProxyCreator;
}

}

这里需要注意两个点:

  • setBeanNames(“per*“):表示匹配前缀以per的所有对象,并为其创建代理对象。
  • setInterceptorNames(“totheforAdvice”):这里的totheforAdvice为上面Bean的方法的名称。

测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.SpringTestAnnotation;

import com.SpringTestAnnotation.TestValue.Per;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
* @Author DragonOne
* @Date 2022/6/10 11:16
* @墨水记忆 www.tothefor.com
*/
public class TestAnnotation {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TestConfig.class);

Per orderS = (Per) applicationContext.getBean("per");
orderS.show();

}
}

输出结果:

1
2
3
before dong
Per show com.SpringTestAnnotation.TestValue.OrderS@7f010382
after dong

配置类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package com.SpringTestAnnotation;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.NameMatchMethodPointcut;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;

/**
* @Author DragonOne
* @Date 2022/6/10 11:16
* @墨水记忆 www.tothefor.com
*/
@ComponentScan(value = "com.SpringTestAnnotation")
public class TestConfig {

@Bean
public DefaultPointcutAdvisor defaultPointcutAdvisor(){
NameMatchMethodPointcut nameMatchMethodPointcut = new NameMatchMethodPointcut();
nameMatchMethodPointcut.setMappedName("show"); //给所有的show方法都加上aop

DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor();
defaultPointcutAdvisor.setPointcut(nameMatchMethodPointcut);

defaultPointcutAdvisor.setAdvice(new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("before dong");
Object proceed = invocation.proceed();
System.out.println("after dong");
return proceed;
}
});
return defaultPointcutAdvisor;
}

@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
return defaultAdvisorAutoProxyCreator;
}


}

注意:setMappedName(“show”);中的show指定的方法的名称。对所有的有此方法的Bean,都会在执行时进行AOP。

测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.SpringTestAnnotation;

import com.SpringTestAnnotation.TestValue.Per;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
* @Author DragonOne
* @Date 2022/6/10 11:16
* @墨水记忆 www.tothefor.com
*/
public class TestAnnotation {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TestConfig.class);

Per orderS = (Per) applicationContext.getBean("per");
orderS.show();

}
}

结果输出:

1
2
3
before dong
Per show com.SpringTestAnnotation.TestValue.OrderS@3967e60c
after dong

从上面可以看出,我们只是定义了一个DefaultAdvisorAutoProxyCreator类型的Bean,所以,在配置类中可以直接使用注解@Import实现。如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package com.SpringTestAnnotation;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.NameMatchMethodPointcut;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;

/**
* @Author DragonOne
* @Date 2022/6/10 11:16
* @墨水记忆 www.tothefor.com
*/
@ComponentScan(value = "com.SpringTestAnnotation")
@Import(DefaultAdvisorAutoProxyCreator.class)
public class TestConfig {

@Bean
public DefaultPointcutAdvisor defaultPointcutAdvisor(){
NameMatchMethodPointcut nameMatchMethodPointcut = new NameMatchMethodPointcut();
nameMatchMethodPointcut.setMappedName("show");

DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor();
defaultPointcutAdvisor.setPointcut(nameMatchMethodPointcut);

defaultPointcutAdvisor.setAdvice(new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("before dong");
Object proceed = invocation.proceed();
System.out.println("after dong");
return proceed;
}
});
return defaultPointcutAdvisor;
}

}

实现效果一样。