理解了前面动态代理对象的原理之后,其实还是有很多不足之处,因为如果在项目中有20多个类,每个类有100多个方法都需要判断是不是要开事务,那么方法调用那里会相当麻烦。
spring中的AOP很好地解决了这个问题,通过 execution表达式 指定哪些包中的那些类 哪些方法 用到事务
execution(public * *(..)) 所有的公共方法
execution(* set*(..)) 以set开头的任意方法
execution(* com.xyz.service.AccountService.*(..)) com.xyz.service.AccountService类中的所有的方法
execution(* com.xyz.service.*.*(..)) com.xyz.service包中的所有的类的所有的方法
execution(* com.xyz.service..*.*(..)) com.xyz.service包及子包中所有的类的所有的方法
execution(* cn.itcast.spring.sh..*.*(String,?,Integer)) cn.itcast.spring.sh包及子包中所有的类的有三个参数
第一个参数为String,第二个参数为任意类型,
第三个参数为Integer类型的方法
springAOP的具体加载步骤:
1、当spring容器启动的时候,加载了spring的配置文件
2、为配置文件中所有的bean创建对象
3、spring容器会解析aop:config的配置
1、解析切入点表达式,用切入点表达式和纳入spring容器中的bean做匹配
如果匹配成功,则会为该bean创建代理对象,代理对象的方法=目标方法+通知
如果匹配不成功,不会创建代理对象
4、在客户端利用context.getBean获取对象时,如果该对象有代理对象则返回代理对象,如果代理对象,则返回目标对象
说明:如果目标类没有实现接口,则spring容器会采用cglib的方式产生代理对象,如果实现了接口,会采用jdk的方式
实例:
引入包
aspectjrt.jar
aspectjweaver.jar
Person.java
1 package cn.itcast.sh.aop; 2 3 4 import java.io.Serializable; 5 6 7 /** 8 * 对象的序列化的作用:让对象在网络上传输,以二进制的形式传输 9 * @author Think 10 * Serializable标示接口 11 */ 12 public class Person implements Serializable{ 13 private Long pid; 14 private String pname; 15 16 public Person(){} 17 18 public Person(String pname){ 19 this.pname = pname; 20 } 21 22 public Long getPid() { 23 return pid; 24 } 25 public void setPid(Long pid) { 26 this.pid = pid; 27 } 28 public String getPname() { 29 return pname; 30 } 31 public void setPname(String pname) { 32 this.pname = pname; 33 } 34 public String getPsex() { 35 return psex; 36 } 37 public void setPsex(String psex) { 38 this.psex = psex; 39 } 40 private String psex; 41 }