SpringBoot-AOP
Aop:面向切面的一种编程
1、加入starter-aop的依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2、写一个UserDaoImpll类:代码如下:
package com.boot.aop.bootaop;
import org.springframework.stereotype.Repository;
@Repository
public class BookDaoImpl {
public void addBook(String name,String author){
System.out.println("bookName:"+name+",bookAuthor:"+author);
}
}
3、想要在这个addBook方法的前后去切入的话,想要在这个方法addBook的前后做一个增强的话:
3.1、写一个切面的Aop类:BookAop,代码如下:
package com.boot.aop.bootaop.aop;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
//在运行期间如果发现这个aop找到了切入点的话就会在BookDaoImpl中的方法
//自动的在方法的前后切入进行增强
@Component
@Aspect
public class BookAop {
//定义切入点,第一个星代表所有的返回类型
//. .代表包及其子包
//第二个星代表所有的类中的
//第三这个星代表所有的方法
//(..)代表参数不受限制。
public static final String POINT_CUT="execution(* com.boot.aop.bootaop.dao..*.*(..))";
@Before(POINT_CUT)
public void before(){
System.out.println("添加图书方法校验前");
}
@After(POINT_CUT)
public void after(){
System.out.println("添加图书成功后");
}
}
然后主函数如下:
package com.boot.aop.bootaop;
import com.boot.aop.bootaop.dao.BookDaoImpl;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class BootAopApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(BootAopApplication.class, args);
BookDaoImpl bookDao = context.getBean(BookDaoImpl.class);
bookDao.addBook("三国演义","罗贯中");
}
}
运行的结果如下:这就是在addBook方法的前后做了一个增强。这就是面向切面的一个编程。目标类是BookDaoImpl。
可以通过JoinPoint对象获取一些属性的值,代码如下:
@After(POINT_CUT)
public void after(JoinPoint jp){
System.out.println(jp.getTarget().getClass());
System.out.println(Arrays.asList(jp.getArgs()));
System.out.println("添加图书成功后");
}
运行的结果如下:获取的是目标类和参数的值。
既然SpringBoot集成了aop,可以通过配置来配置Aop。
1、基于Spring的Aop写法:
spring.aop.auto=true:是否启用aop
spring.aop.proxy-target-class=false:代理方式有接口使用jdk动态代理,如果没有接口使用cglib代理,默认的值为false。
代码如下:
spring.aop.auto=true
spring.aop.proxy-target-class=false
主函数里加上一行代码,来获取接口的类型;
System.out.println(bookDao.getClass());
运行的结果如下:当一个没有实现接口的类交给Spring容器做Aop做代理的话,是cglib代理。
如果是实现接口的类的话就是jdk的动态代理,代码如下:
但是如果一个类去实现接口的话也可以强制使用cglib的代理,配置如下:
下面的配置改为true即可。
再次运行下:
这两个代理的区别:jdk的动态代理只能代理接口,而cglib的代理有无接口都可以代理。
在Spring如果使用这个类的jdk动态代理的话,不能用他的实现类来获取的。
如果有多个类实现接口的话需要加一个别名的参数。
2、基于SpringBoot的做法:@EnableAutoProxyClass
exposeProxy属性表示如果使用true就可以使用AopContext对象获取当前代理对象,false则不能使用
proxyTargetClass:true表示使用cglib的动态代理,false表示使用jdk代理。
代码如下:
运行的结果如下:
总结: