AOP的通知类型:
aop联盟定义aop通知类型,spring对aop联盟规范支持。
aop联盟定义5种通知
前置通知org.springframework.aop.
MethodBeforeAdvice在目标方法执行前实施增强
后置通知org.springframework.aop.
AfterReturningAdvice在目标方法执行后实施增强
环绕通知org.aopalliance.intercept.MethodInterceptor在目标方法执行前后实施增强异常抛出通知org.springframework.aop.
ThrowsAdvice在方法抛出异常后实施增强
引介通知org.springframework.aop.IntroductionInterceptor(了解)对一个类进行增强(添加方法或属性等)
在目标类中添加一些新的方法和属性
如果使用aop联盟规范进行aop开发,所有的通知必须实现接口。(底层为了确定通知方法名称)
AOP的半自动代理(不带有切入点的切面---所有方法)
1.切面类需要总结:
需要根据AOP联盟确定一个通知类型:这里使用
环绕通知(环绕通知需要手动开启方法)所以切面类随便写,随便实现一个通知类型,重写里面的invok方法在,通过参数调用
proceed()执行目标类,前后可以写代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| package com.mickeymouse.proxy;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
/**
*切面类:包含两个通知(增强)
环绕通知必须手动执行方法
*@authorMickey-Mouse
*
*/
public class MyAspect implements MethodInterceptor{
public Objectinvoke(MethodInvocationmi) throws Throwable{
System.out.println( "已校验是否符合身份" );
//环绕通知必须手动执行方法
Objectobject=mi.proceed();
System.out.println( "方法已经执行完--->后处理" );
return object;
}
}
|
2.目标类(已实现接口)1
2
3
4
5
6
7
8
9
10
11
12
13
| package com.mickeymouse.proxy;
public class ProductsServiceImpl implements ProductsService{
/**
*目标类:
*里面有两个连接点
*/
public void addProducts(){
System.out.println( "添加商品成功" );
}
public void updateProducts(){
System.out.println( "修改商品成功" );
}
}
|
3.半自动代理XML配置与AOP的自动代理的区别在于:
半自动代理没有使用AOP约束,要手动配置代理类与目标类的关系
半自动代理是基于ProxyFactoryBean的代理类:缺点:*配置麻烦:*需要为每一个要增强的类配置一个ProxyFactoryBean.(只要有增强,就需要写一个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
| <? 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"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd">
<!--beandefinitionshere-->
<!--半自动代理模式-->
<!--生成切面类-->
< bean id = "myAspect" class = "com.mickeymouse.proxy.MyAspect" />
<!--生成目标类-->
< bean id = "productsService" class = "com.mickeymouse.proxy.ProductsServiceImpl" />
<!--让Spring来创建代理工厂对象-->
< bean id = "proxyFactoryBean" class = "org.springframework.aop.framework.ProxyFactoryBean" >
<!--设置目标类-->
< property name = "target" ref = "productsService" ></ property >
<!--设置切面类"名字"-->
< property name = "interceptorNames" value = "myAspect" ></ property >
<!--设置切面类需要连接的接口(optimize与接口二选一即可,Spring可以自动识别,接口就动态代理,没有就CGLIB)-->
< property name = "proxyInterfaces" value = "com.mickeymouse.proxy.ProductsService" ></ property >
<!--是否强制使用使用CGLIB-->
< property name = "optimize" value = "true" ></ property >
</ bean >
</ beans >
|
测试类:
1
2
3
4
5
6
7
| @Test
public void test1(){
ApplicationContextapplicationContext= new ClassPathXmlApplicationContext( "applicationContext.xml" );
ProductsServicebean=applicationContext.getBean( "proxyFactoryBean" ,ProductsService. class );
bean.addProducts();
bean.updateProducts();
}
|
结果:
AOP的半自动代理:(配置带有切入点的切面---->个别方法)(了解)
配置文件:(其他部分是一样的,同上)
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
| <? 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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd">
<!--Spring帶有切入点的切面===============-->
<!--配置目标类-->
< bean id = "customerDao" class = "com.itheima.spring.demo4.CustomerDao" />
<!--配置通知:(环绕通知)-->
< bean id = "myAroundAdvice" class = "com.itheima.spring.demo4.MyAroundAdvice" />
<!--配置带有切入点的切面-->
< bean id = "myAdvisor" class = "org.springframework.aop.support.RegexpMethodPointcutAdvisor" >
<!--表达式:正则表达式:.:任意字符*:任意次数-->
<!--拦截所有方法-->
<!--<propertyname="pattern"value=".*"/>-->
<!--只拦截update方法-->
<!--<propertyname="pattern"value="com\.itheima\.spring\.demo4\.CustomerDao\.update"/>-->
<!--拦截update和delete方法-->
<!--<propertyname="patterns"value="com\.itheima\.spring\.demo4\.CustomerDao\.update,com\.itheima\.spring\.demo4\.CustomerDao\.delete"/>-->
<!--拦截所有以save和update结束名的方法-->
< property name = "patterns" value = ".*save.*,.*update.*" />
<!--配置增强-->
< property name = "advice" ref = "myAroundAdvice" />
</ bean >
<!--配置生成代理-->
< bean id = "proxyFactoryBean" class = "org.springframework.aop.framework.ProxyFactoryBean" >
<!--配置目标-->
< property name = "target" ref = "customerDao" />
<!--配置代理目标类-->
< property name = "proxyTargetClass" value = "true" />
<!--配置拦截的名称-->
< property name = "interceptorNames" value = "myAdvisor" />
</ bean >
</ beans >
|