Spring_Aop的xml和注解的使用

本文内容纲要:Spring_Aop的xml和注解的使用

动态代理:

目的:在不改变源代码的情况下,对方法进行增强!

动态代理又分为两种:

1.第一个就是基于接口的动态代理,他是由jdk提供的

2.基于子类的动态代理:cglib提供的:要想使用基于子类的动态代理:就必须得导入cglib的jar包

特性:被代理对象的任意方法

Spring_aop:总结

aop(Aspect Oriented Programming) :面向切面编程

切面:相对于业务主线的额外的功能模块

在不改变程序源代码的情况下对方法进行增强

aop的底层原理就是动态代理

aop的底层他会自动的根据代码,选择是使用基于还是使用子类的动态代理!

使用aop进行编程有啥好处呢?

1.简化业务代码

2.维护简单

Aop相关术语

Joinpoint(连接点):执行的方法

pointcut(切入点):被增强的方法

Advice(通知/增强):就是额外的功能模块

前置通知

后置通知

异常通知

最终通知

环绕通知

Aspect(切面):

对那个方法进行怎样的增强

学习Aop重点关注的事情是啥呢?

1.重点关注的是一个一个的额外的功能模块

2.aop的配置

第三 spring Aop的开发流程

定义一个切面类

普通的Java类,在这个类中通过一个一个的方法对目标对象进行增强

2.配置Aop

在xml里面配置文件中aop

i.将切面类交给spring管理

ii.声明Aop配置

aop:config

iii.定义切入点

aop:pointcut

iiii.定义通知类型

<aop:aspect ref = "切面类的引用">

前置通知

<aop:before method="切面类的方法名" pointcut-ref="切入点表达式是引用"/>

后置通知<aop:afterRunturning method="切面类的方法名" pointcut-ref="切入点表达式是引用"/>

异常通知<aop:after-throwing method="切面类的方法名" pointcut-ref="切入点表达式是引用"/>

最终通知<aop:after method="切面类的方法名" pointcut-ref="切入点表达式是引用"/>

注意:异常通知只有出现了异常了 才会有通知

</aop:aspect>

基于注解的Aop配置(结合xml)

1.将切面类交给spring管理

2.使用注解的形式代替xml中的aop的配置

3.使用注解配置spring的ioc或者aop的时候都需要开启对注解的支持!

注意:使用注解配置Aop和xml配置Aop在后置通知的时候,有一些差别!

注解的配置:是最后执行后置通知!

纯注解配置Aop

1.声明配置类

2.开启对ioc的支持

3.开启对aop注解的支持

@EnableAspectJAutoProxy

开发步骤以及代码的解释

aop:config

<aop:pointcut expression="execution(* cn.itcast.service.impl..*.*(..))" id="pt"/>

<aop:aspect ref="logger">

<aop:before method="before" pointcut-ref="pt"/>

这是xml里面的配置

注解配合xml使用代码以及解释

<context:component-scan base-package="cn.itcast"></context:component-scan>

aop:aspectj-autoproxy</aop:aspectj-autoproxy>

/*

* 切面类:

* 对目标对象进行日志部分的增强是通过此类中的方法来实现

* 在切面类上

* 定义切面类

* 在切面方法上

* 使用注解的形式定义通知类型

*/

@Component("logger")

@Aspect

public class Logger {//这是配置到类上的

/**

* 抽取切入点表达式

* @Pointcut:定义切入点表达式

* 这个注解需要配置到方法上,这个方法是一个空的方法

* 应用这个切入点表达式的时候,只需要引入方法名就可以了

* 但是需要 方法名() 需要加括号

*/

@Pointcut(value="execution(* cn.itcast.service.impl..*.*(..))")//注意:类名前面那两个点改成一个点也是可以的

@Pointcut(value="execution(* cn.itcast.service.impl.*.add*(..))")//这是指定对那个方法进行增强

public void pt() {//定义一个通用的,这样前置通知,后置通知等等用的时候只需要引用这个方法名就行了

}

/**

* 定义前置通知

* @Before :

* value : 可以是一个切入点表达式,也可以是一个切入点表达式的引用

* 切入点表达式

*/

@Before("pt()")

public void before() {

System.out.println("进入方法之前打印日志");

}

*这是注解配置xml的方法

纯注解的配置方式

/*

* 切面类:

* 对目标对象进行日志部分的增强是通过此类中的方法来实现

* 在切面类上

* 定义切面类

* 在切面方法上

* 使用注解的形式定义通知类型

*/

@Component("logger")

@Aspect

public class Logger {

/**

* 抽取切入点表达式

* @Pointcut:定义切入点表达式

* 这个注解需要配置到方法上,这个方法是一个空的方法

* 应用这个切入点表达式的时候,只需要引入方法名就可以了

* 但是需要 方法名() 需要加括号

*/

@Pointcut(value="execution(* cn.itcast.service.impl..*.*(..))")

public void pt() {

}

/**

* 定义前置通知

* @Before :

* value : 可以是一个切入点表达式,也可以是一个切入点表达式的引用

* 切入点表达式

*/

@Before("pt()")

public void before() {

System.out.println("进入方法之前打印日志");

}

@AfterReturning("pt()")

public void afterReturning() {

System.out.println("执行目标方法得到返回值后打印日志");

}

@AfterThrowing("pt()")

public void afterThrowing() {

System.out.println("抛出异常打印日志");

}

@After("pt()")

public void after() {

System.out.println("在最终代码块中打印日志");

}

//5.定义环绕通知

/**

* 环绕通知是spring提供的一种

* 让程序员手动指定要执行的增强方法的一种手段,

* 在此方法中可以根据需求自定义以上4中通知类型

* 在环绕通知中,需要手动去调用被增强的方法

* 借助spring提供的一个对象ProceedingJoinPoint

* 此对象中有一个方法,可以调用被增强的方法

* pjp.proceed();执行被增强的的方法

* eg:动态代理中的,method.invoke();

*

* @throws Throwable

*/

@Around("execution(* cn.itcast.service.impl..*.*(..))")

public Object around(ProceedingJoinPoint pjp) throws Throwable {

System.out.println("前置通知");

Object obj = null;

try{

obj = pjp.proceed();

System.out.println("后置通知");

}catch(Exception e){

System.out.println("异常通知");

e.printStackTrace();

}finally{

System.out.println("最终通知");

}

return obj;

}

}

/spring的配置类

//在配置类中替换xml配置文件中的剩余配置项

/**

* 1。声明配置类

* 2。开启对ioc的支持

* 3。开启对AOP注解的支持

* @EnableAspectJAutoProxy

*

*/

@Configuration

@ComponentScan(basePackages="cn.itcast")

@EnableAspectJAutoProxy

public class Config {

}

public class Client {

public static void main(String[] args) {

//测试ioc的配置

//ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");

ApplicationContext ac = new AnnotationConfigApplicationContext(Config.class);

CustomerService customerService = (CustomerService)ac.getBean("customerService");

customerService.updateCustomer();

}

}

这是纯注解的方式

Aop事物案例

@Component("logger")

@Aspect

public class Logger {

@Pointcut(value="execution(* cn.crm.service.impl..*.*(..))")

public void pt(){

}

@Around(value="pt()")

public Object tx(ProceedingJoinPoint pjp) throws Throwable{

Session session = null;

Transaction tx = null;

Object obj = null;

try {

session = HibernateUtils.getCurrentSession();

tx = session.beginTransaction();

obj = pjp.proceed();

tx.commit();

} catch (Exception e) {

System.out.println("出现异常了");

tx.rollback();

}finally {

System.out.println("最终执行的代码");

}

return obj;

}

}

public class Client{

public static void main(String[] args) {

ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");

CustomerService customerService = (CustomerService)ac.getBean("customerService");

Customer customer = new Customer();

customer.setCustName("hello");

customerService.addCustomer(customer);

}

}

xml配置:

<context:component-scan base-package="cn.crm"></context:component-scan>

aop:aspectj-autoproxy</aop:aspectj-autoproxy>

这是一个小小的Aop的事物案例,当然Spring也提供了事物的支持,但是今天只做了个Aop的事物,希望对大家有帮助

本文内容总结:Spring_Aop的xml和注解的使用

原文链接:https://www.cnblogs.com/guanzhuang/p/7684690.html

以上是 Spring_Aop的xml和注解的使用 的全部内容, 来源链接: utcz.com/z/296888.html

回到顶部