首页 > 代码库 > Java--简单的Spring AOP配置以及AOP事物管理,JDK/GCLib动态代理

Java--简单的Spring AOP配置以及AOP事物管理,JDK/GCLib动态代理

一、看一下简单的通过XML的AOP配置

1.首先创建一个简单的Student类

public class Student {    private Integer age;    private String name;    public void setAge(Integer age) {        this.age = age;    }    public Integer getAge() {        System.out.println("Age : " + age);        return age;    }    public void setName(String name) {        this.name = name;    }    public String getName() {        System.out.println("Name : " + name);        return name;    }    public void printThrowException() {        System.out.println("Exception raised");        throw new IllegalArgumentException();    }}

2.创建一个简单的aspect切面class

public class Logging {/**     * This is the method which I would like to execute     * before a selected method execution.     */public void beforeAdvice() {        System.out.println("Going to setup student profile.");    }    /**     * This is the method which I would like to execute     * after a selected method execution.     */public void afterAdvice() {        System.out.println("Student profile has been setup.");    }    /**     * This is the method which I would like to execute     * when any method returns.     */    public void afterReturningAdvice(Object retVal) {        System.out.println("Returning:" + retVal.toString());    }    /**     * This is the method which I would like to execute     * if there is an exception raised.     */    public void AfterThrowingAdvice(IllegalArgumentException ex) {        System.out.println("There has been an exception: " + ex.toString());    }}

3.SpringAOP.xml配置

    <bean id="student" class="com.seeyon.SpringBean.aop.Student" p:name="yangyu" p:age="27"></bean>    <bean id="logging" class="com.seeyon.SpringBean.aop.Logging"></bean>    <!--XML方式配置Spring AOP-->    <aop:config>        <aop:aspect id="log" ref="logging">   【切面class】            <aop:pointcut id="studentMethod" expression="execution(* com.seeyon.SpringBean.aop.Student.get*(..))"/> 【切点】            <aop:before pointcut-ref="studentMethod" method="beforeAdvice"/>  【方法执行之前触发切面class的beforeAdvice方法】            <aop:after pointcut-ref="studentMethod" method="afterAdvice"/>    【方法执行之后触发切面class的afterAdvice方法】        </aop:aspect>    </aop:config>

分析一下这个execution(* com.seeyon.SpringBean.aop.Student.get*(..))切点表达式:

(1)第一个*代表方法的返回值是任意的

(2)get*代表以get开头的所有方法

(3)(..)代表方法的参数是任意个数

 

4.main方法

public class test {    public static void main(String[] args) {        ApplicationContext context =                new ClassPathXmlApplicationContext("SpringAop.xml");        Student student = (Student) context.getBean("student");        student.getName();//        student.getAge();//        student.printThrowException();    }}

5.输出结果

Going to setup student profile.Name : yangyuStudent profile has been setup.

 

二、Spring AOP注解的使用。

1.首先创建一个简单的Student类(同一.1中,请看上面??)

2.创建一个简单的aspect切面class,并加上@注解配置。

@Aspect   //表示是一个aspect切面class,注解以后可以被Spring扫描到public class Logging {    @Pointcut("execution(* com.seeyon.SpringBean.aop.Student.get*(..))")  //定义切点    public void getMethod(){}; //切点方法,方法名称相当于ID,方法名称随便取    /**     * This is the method which I would like to execute     * before a selected method execution.     */    @Before("getMethod()")   //切点方法执行之前执行@Before    public void beforeAdvice() {        System.out.println("Going to setup student profile.");    }    /**     * This is the method which I would like to execute     * after a selected method execution.     */    @After("getMethod()")   //切点方法执行之后执行@After    public void afterAdvice() {        System.out.println("Student profile has been setup.");    }    /**     * This is the method which I would like to execute     * when any method returns.     */    @AfterReturning(pointcut = "getMethod()",returning = "retVal")//切点方法返回值完成后执行@AfterReturning    public void afterReturningAdvice(Object retVal) {        System.out.println("Returning:" + retVal.toString());    }    /**     * This is the method which I would like to execute     * if there is an exception raised.     */    @AfterThrowing(pointcut = "getMethod()",throwing = "ex")//切点方法抛出异常之后执行@AfterThrowing    public void AfterThrowingAdvice(IllegalArgumentException ex) {        System.out.println("There has been an exception: " + ex.toString());    }}

3.SpringAOP.xml配置

    <bean id="student" class="com.seeyon.SpringBean.aop.Student" p:name="yangyu" p:age="27"></bean>    <bean id="logging" class="com.seeyon.SpringBean.aop.Logging"></bean>    <!--注解方式配置Spring AOP,Spring会自动到已注册的bean中去寻找@Aspect注解标记的class-->    <aop:aspectj-autoproxy/>

4.mian方法

public class test {    public static void main(String[] args) {        ApplicationContext context =                new ClassPathXmlApplicationContext("SpringAop.xml");        Student student = (Student) context.getBean("student");        student.getName();//        student.getAge();//        student.printThrowException();    }}

5.输出结果

Going to setup student profile.Name : yangyuStudent profile has been setup.Returning:yangyu

 

注意事项:

<aop:config proxy-target-class="true"></aop:config><aop:aspectj-autoproxy proxy-target-class="true"/>

1.如果不设置proxy-target-class属性或者设置成false:

(1)代理类实现了接口,那么AOP实际上是使用的JDK的自动代理,代理的接口。

(2)代理类没有接口,那么还是使用的CGLib进行代理。

 

2.如果将proxy-target-class属性设置成true,那么将始终使用CGLib进行代理。

 

JDK动态代理与CGLib动态区别:

1、JDK动态代理:JDK的动态代理依靠接口实现,如果有些类并没有实现接口,则不能使用JDK代理,这就要使用cglib动态代理了。

2、CGLib动态代理:cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。

 

可以得出一个结论:CGLib 可以代理任何的类。

那为什么还要用 JDK 的动态代理呢?肯定您会这样问:

根据多年来实际项目经验得知:CGLib 创建代理的速度比较慢,但创建代理后运行的速度却非常快,而 JDK 动态代理正好相反。如果在运行的时候不断地用 CGLib 去创建代理,系统的性能会大打折扣,所以建议一般在系统初始化的时候用 CGLib 去创建代理,并放入 Spring 的ApplicationContext 中以备后用。

 

三、通过AOP进行事务管理

1.SpringAOP.xml配置

    <!--事物管理-->    <aop:config proxy-target-class="true"> //使用GCLib动态代理模式        <aop:pointcut id="studentGetMethod"                      expression="execution(* com.seeyon.SpringBean.aop..*.*(..))" /> //定义切点        <aop:advisor pointcut-ref="studentGetMethod" advice-ref="txAdvice" />    </aop:config>    <tx:advice id="txAdvice" transaction-manager="txManager">        <tx:attributes>            <tx:method name="*" />             //对有所方法进行事物管理        </tx:attributes>    </tx:advice>    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"/>

分析一下execution(* com.seeyon.SpringBean.aop..*.*(..))这个切点表达式:

(1)第一个*表示方法的返回值是任意的

(2)aop..表示aop包以及aop的子包

(3)aop..*表示aop包以及aop的子包下的所有class

(4)aop..*.*表示aop包以及aop的子包下的所有class的所有方法

(5)(..)表示方法参数任意

 

此处简单列举了一个TransactionManager:org.springframework.jdbc.datasource.DataSourceTransactionManager,并且没有对其进行属性注入,请根据自己的项目合理选择TransactionManager。

 

Java--简单的Spring AOP配置以及AOP事物管理,JDK/GCLib动态代理