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;@Repositorypublic 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@Aspectpublic 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;@SpringBootApplicationpublic 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=truespring.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代理。
代码如下:
运行的结果如下:
总结: