Spring笔记4
1. 不用Aop使用jdk的代理实现拦截,PersonServiceBean要求必须实现接口
接口
1 package cn.itcast.service;
2
3 public interface PersonService {
4
5 public abstract void save();
6
7 }
被拦截的类
1 package cn.itcast.service.impl;
2
3 import cn.itcast.service.PersonService;
4
5 public class PersonServiceBean implements PersonService {
6
7
8 public String name;
9
10 public PersonServiceBean() {
11 }
12
13 public PersonServiceBean(String name) {
14 this.name = name;
15 }
16
17 public void save(){
18 System.out.println("我是sava方法");
19 }
20
21 public String getName() {
22 return name;
23 }
24
25 }

2. 如果类没有实现接口使用cglib实现 ,导入.../lib/cglib下的cglib-nodep-2.1_3.jar文件
代理类
1 package cn.itcast.aop;
2
3 import java.lang.reflect.Method;
4
5 import cn.itcast.service.impl.PersonServiceBean;
6
7 import net.sf.cglib.proxy.Enhancer;
8 import net.sf.cglib.proxy.MethodInterceptor;
9 import net.sf.cglib.proxy.MethodProxy;
10
11 public class CGlibFactory implements MethodInterceptor{
12 public Object tagetObject;
13
14 public Object createProxyInstance(Object tagetObject){
15 this.tagetObject = tagetObject;
16 Enhancer enhancer = new Enhancer();
17 //指定父类,重写父类的所有非final方法
18 enhancer.setSuperclass(this.tagetObject.getClass());
19 //指定回调函数,类实现MethodInterceptor接口
20 enhancer.setCallback(this);
21 return enhancer.create();
22 }
23
24 @Override
25 public Object intercept(Object proxy, Method method, Object[] args,
26 MethodProxy methodProxy) throws Throwable {
27 PersonServiceBean bean = (PersonServiceBean)this.tagetObject;
28 Object result=null;
29 if(bean.getName()!=null){
30 //将方法的调用委派给目标对象
31 result = methodProxy.invoke(tagetObject, args);
32 }
33 return null;
34 }
35 }
测试类
1 package cn.itcast.test; 2 3 import org.junit.Test; 4 5 import cn.itcast.aop.CGlibFactory; 6 import cn.itcast.aop.ProxyFactroy; 7 import cn.itcast.service.PersonService; 8 import cn.itcast.service.impl.PersonServiceBean; 9 10 public class AopTest { 11 @Test public void aopTest(){ 12 ProxyFactroy factory = new ProxyFactroy(); 13 //PersonService用接口类,传参的时候用非接口类,传名字的时候正常,不传名字的时候被拦截 14 PersonService service = (PersonService) factory.createProxyInstance(new PersonServiceBean("xxx")); 15 service.save(); 16 } 17 @Test public void aopTest2(){ 18 CGlibFactory factory = new CGlibFactory(); 19 //传名字的时候正常,不传名字的时候被拦截 20 PersonServiceBean service = (PersonServiceBean) factory.createProxyInstance(new PersonServiceBean("xxx")); 21 service.save(); 22 } 23 }
3. AOP的概念:
Aspect(切面):对横切性关注点的一个抽象,比如上面的Factory类
joinpoint(连接点):指被拦截到的点,在Spring中指方法,比如上面的save方法
Pointcut(切入点):是指我们要对哪些joinpoint进行拦截的定义
Advice(通知):指拦截到joinpoint之后要做的事情,通知分为前置通知,后置通知,例外通知,最终通知,环绕通知
Target(目标对象):代理的目标对象
Weave(织入):将Aspect应用到target对象并导致Proxy对象创建的过程
Introduction(引入):在不修改代码的前提下,Introduction可以为类动态的添加一些方法或Field
4. 使用Spring的aop实现切面编程:
1)引入aop的jar包
2)加入命名空间,第5,10行,第11行打开aop注解
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xmlns:aop="http://www.springframework.org/schema/aop" 6 xsi:schemaLocation="http://www.springframework.org/schema/beans 7 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 8 http://www.springframework.org/schema/context 9 http://www.springframework.org/schema/context/spring-context-2.5.xsd 10 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd "> 11 <aop:aspectj-autoproxy></aop:aspectj-autoproxy> 12 </beans>
3)创建要拦截的bean以及接口
1 package cn.itcast.service; 2 3 4 import java.util.List; 5 import java.util.Map; 6 import java.util.Properties; 7 import java.util.Set; 8 9 public interface PersonService { 10 11 public abstract void save(); 12 public abstract void update(); 13 public abstract String getPeresonName(); 14 }
1 package cn.itcast.service.imp; 2 3 import cn.itcast.service.PersonService; 4 5 public class PersonServiceBean implements PersonService { 6 7 @Override 8 public String getPeresonName() { 9 return "xxx"; 10 11 } 12 13 @Override 14 public void update() { 15 System.out.println("update"); 16 17 } 18 19 @Override 20 public void save() { 21 System.out.println("save"); 22 23 } 24 25 }
4)创建切面,切入点,以及前置通知
1 package cn.itcast.service; 2 3 import org.aspectj.lang.annotation.Aspect; 4 import org.aspectj.lang.annotation.Before; 5 import org.aspectj.lang.annotation.Pointcut; 6 7 @Aspect//切面 8 public class Interceptor { 9 //切入点,(返回值,然后是包名,类名,方法,参数)*代表任意,..代表所有 10 @Pointcut("execution(* cn.itcast.service.imp.PersonServiceBean.*(..))") 11 private void anyWethod(){}//声明一个切入点 12 13 //前置通知,参数为切入点 14 @Before("anyWethod()") 15 public void doAcessCheak(){ 16 System.out.println("前置通知"); 17 } 18 19 }
5)将切面以及bean交给Spring管理
1 <bean id="myInterceptor" class="cn.itcast.service.Interceptor"></bean> 2 <bean id="personService" class="cn.itcast.service.imp.PersonServiceBean"></bean>
6)测试
ApplicationContext ctr = new ClassPathXmlApplicationContext("beans.xml"); PersonService personService = (PersonService) ctr.getBean("personService"); personService.save();
控制台会输出前置通知的内容,然后输出save方法中的内容
5. 前置通知
1 @Before("anyWethod()") 2 public void doAcessCheck(){ 3 System.out.println("前置通知"); 4 }
@Before("anyWethod() && args(name)")//表示拦截参数为一个且是String类型的方法
public void doAcessCheck(String name){
System.out.println("前置通知"+name);
}
6. 后置通知
1 @AfterReturning("anyWethod()") 2 public void doAccessCheckAfter(){ 3 System.out.println("后置通知"); 4 }
1 @AfterReturning(pointcut="anyWethod()" ,returning="result" )//表示拦截返回值为String类型的方法 2 public void doAccessCheckAfter(String result){ 3 System.out.println("后置通知"+result); 4 }
7. 最终通知
1 @After("anyWethod()") 2 public void doAfter(){ 3 System.out.println("最终通知"); 4 }
8 例外通知
1 @AfterThrowing("anyWethod()") 2 public void dofterThrowing(){ 3 System.out.println("例外通知"); 4 }
1 @AfterThrowing(pointcut="anyWethod()",throwing="e")//表示拦截参数为Exception的异常 2 public void dofterThrowing(Exception e){ 3 System.out.println("例外通知"+e); 4 }
9. 环绕通知
1 @Around("anyWethod()") 2 public Object doAround(ProceedingJoinPoint pjp) throws Throwable{ 3 System.out.println("进入方法"); 4 Object result = pjp.proceed(); 5 System.out.println("退出方法"); 6 return result; 7 }
10. 用xml方式实现,不使用注解
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xmlns:aop="http://www.springframework.org/schema/aop" 6 xsi:schemaLocation="http://www.springframework.org/schema/beans 7 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 8 http://www.springframework.org/schema/context 9 http://www.springframework.org/schema/context/spring-context-2.5.xsd 10 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd "> 11 <aop:aspectj-autoproxy></aop:aspectj-autoproxy> 12 <bean id="personService" class="cn.itcast.service.imp.PersonServiceBean"></bean> 13 <bean id="sapectBean" class="cn.itcast.service.Interceptor"></bean> 14 <aop:config> 15 <aop:aspect id="asp" ref="sapectBean"> 16 <aop:pointcut id="aspCut" expression="execution(* cn.itcast.service.imp.PersonServiceBean.*(..))"/> 17 <aop:before pointcut-ref="aspCut" method="doAcessCheck"/> 18 <aop:after-returning pointcut-ref="aspCut" method="doAccessCheckAfter"/> 19 <aop:after-throwing pointcut-ref="aspCut" method="dofterThrowing"/> 20 <aop:after pointcut-ref="aspCut" method="doAfter"/> 21 <aop:around pointcut-ref="aspCut" method="doAround"/> 22 </aop:aspect> 23 </aop:config> 24 </beans>
aop
我要青春像陈孝正一样,不能有一毫米的误差!
我要青春像合伙人一样,为了自尊而战!

接口
浙公网安备 33010602011771号