三种代理模式:静态代理,动态代理,Spring cglib代理
功能:权限校验,日志管理,事务管理
代理模式:首先,想到代理应该就可以想象到中介,其实在现实生活中中介有很多,我们最常见也是最熟悉的就是租房中介,房东与租客直接就是中介,我们将我们的要求告诉中介,中介根据我们的需求找房子与房东联系
明星和经纪人
代理:静态代理,动态代理,cglib代理
package com.biyi.sttic;
public class Groxp {
//这里其实就是商家
//在这里商家与经纪人进行沟通,在这经纪人就是代理对象
public static void main(String[] args) {
Manage m = new Manage();
m.sing();
m.dance();
}
}
//这是一个经纪人的类,经济人要想知道start类的共功能那么就要通过接口进行实现
class Manage implements Skill{
//引入目标对象, 在这里就是引入
Star star=new Star();
@Override
public void sing() {
System.out.println("经纪人与商家沟通");
System.out.println("在哪里工作");
System.out.println("签合同");
System.out.println("给钱");
star.sing();
}
@Override
public void dance() {
System.out.println("经纪人与商家沟通");
System.out.println("在哪里工作");
System.out.println("签合同");
System.out.println("给钱");
star.dance();
}
}
interface Skill{
void sing();
void dance();
}
//在这里这个类就是明星,切在明星下面有两个方法,唱歌和跳舞
class Star implements Skill{
public void sing(){
System.out.println("唱的不错");
}
public void dance(){
System.out.println("跳到不错");
}
}
执行结果为
代理模式主要解决service层的问题
如果写在一个类不太懂,那么可以通过三层代码结构进行实现
package com.biyi.controller;
import com.biyi.service.UserService;
import com.biyi.user.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
@Autowired//在这个时候就有两个bean(实现类)所以这个时候就要标示bean的id名称
@Qualifier("static")
//当接口有多个实现类的时候那么就需要我们进行标示这两个注解必须使用
private UserService userService;
public void addUser(User user){
userService.addUser(user);
}
public void updatUser(User user){
userService.addUser(user);
}
public void deleteById(int id){
userService.deleteById(id);
}
}
service实现类
package com.biyi.service.implment;
import com.biyi.dao.Dao;
import com.biyi.service.UserService;
import com.biyi.user.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service("UserServiceImplment")
public class UserServiceImplment implements UserService {
@Autowired
private Dao dao;
@Override
public void addUser(User user) {
System.out.println("每个方法都需要写这样的代码");
System.out.println("权限校验");
System.out.println("事务管理");
System.out.println("开启事务");
try {
dao.addUser(user);
System.out.println("提交事务");
} catch (Exception e) {
e.printStackTrace();
System.out.println("事务回滚");
}finally{
System.out.println("关闭链接");
}
}
@Override
public void updateUser(User user) {
System.out.println("权限校验");
System.out.println("事务管理");
System.out.println("开启事务");
try {
dao.updateUser(user);
System.out.println("提交事务");
} catch (Exception e) {
e.printStackTrace();
System.out.println("事务回滚");
}finally{
System.out.println("关闭链接");
}
}
@Override
public void deleteById(int id) {
dao.deleteById(id);
}
}
代理类
package com.biyi.service.implment;
import com.biyi.service.UserService;
import com.biyi.user.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
/*
* UserServiceStatis在这里就是上一个manage类就是经纪人
*
* */
@Service("static")
public class UserServiceStatis implements UserService {
@Autowired
@Qualifier("UserServiceImplment")
private UserService userService;
@Override
public void addUser(User user) {
System.out.println("权限校验");
System.out.println("事务管理");
System.out.println("开启事务");
try {
userService.updateUser(user);
System.out.println("提交事务");
} catch (Exception e) {
e.printStackTrace();
System.out.println("事务回滚");
}finally{
System.out.println("关闭链接");
}
}
@Override
public void updateUser(User user) {
}
@Override
public void deleteById(int id) {
}
}
静态代理模式或出现代码冗余和混乱这种情况,所以我们重点说一下到哪个台代理
什么是动态代理:它通过java反射机制(关于java反射请看这里),获取某个被代理类的所有接口,并创建代理类或者接口
动态代理也称为jdk代理,使用jdk的一个procy类创建代理对象
package com.biyi.action;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Poxy {
public static void main(String[] args) {
//这是商家的类
//同样商家是与代理这进行对接
/*
* newProxyInstance(ClassLoader loader,代理就是地理star类,目标对象的类加载器 相当于new 目标对象
Class>[] interfaces,目标对象实现是接口
InvocationHandler h)创建代理对象的回调函数
*
*
* */
//传过来是目标对象是谁,也就是star,真正的目标对象是star,也就是说真正唱歌个或者跳舞的是star
Star star=new Star();
//如何拿到类加载器,那么通过getclass
Class<? extends Star> aClass = star.getClass();
//说明如果在这里不进行强制类型转换是无法调用sing放方法和dance方法,所以需要进行强制类型转化
//我们是不是要创建代理对象,就newProxyInstance这一个方法就搞定了,
//我们要那star的代理对象,star是通过接口进行代理,所以这个地方需要强制类型转换
//这里aClass.getClassLoader(),类加载器,这里是代理star所以是star的类加载器,所以肯定要传过来star对象
//getInterfaces(),目标对象实现的接口
//new InvocationHandler() 创建代理对象的一个回调函数,在这里其实我们不管是接口,我们也直接去new
Skill dailiobj= (Skill) Proxy.newProxyInstance(aClass.getClassLoader(), aClass.getInterfaces(), new InvocationHandler() {
//这是匿名内部类,回调函数,在jdk8之后出现了lambad表达式
/*
这是创建代理对象的回调函数 invoke
* proxy:代理对象
* method:代理对象的方法,也就是执行功能的方法
* args:代理对象的方法的参数
* Throwable:异常处理
* */
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("商家与经纪人沟通");
System.out.println("签合同");
System.out.println("给钱");
/*
* Object obj: 目标对象
* Object... args:参数
*
* */
//Object obj =null;
//我们开始执行方法,方法在哪里,在method里面
// 其实这里是目标对象,所以在这里的参数
Object obj=method.invoke(star, args);
System.out.println("关闭链接");
return obj;
}
});
//代理对象创建完成,我们去调用代理对象的方法
//代理对象的方法
//说明如果在这里不进行强制类型转换是无法调用sing放方法和dance方法,
dailiobj.sing();
dailiobj.dance();
}
}
interface Skill{
void sing();
void dance();
}
//目标类
class Star implements Skill{
public void sing(){
System.out.println("唱歌好听");
}
public void dance(){
System.out.println("跳舞");
}
}
静态和动态是必须要有接口的
我们是通过传入接口,底层实现接口,才能实现功能添加的效果,那么他致命的缺点就是必须要依赖接口,如果遇见没有接口的,那么jdk动态代理就无法实现;
在Spring中也有一种代理模式,成为cglib代理,在cglib代理中要么有接口(如果有接口默认使用jdk代理),要么有继承(cglib代理),其实在Spring中默认使用的是jdk代理,只有没有接口的时候才使用cglib代理,所以借口呢是很重要的
package com.biyi.action;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Objects;
public class Poxy {
public static void main(String[] args) {
//这是商家的类
//同样商家是与代理这进行对接
/*
* newProxyInstance(ClassLoader loader,目标对象的类加载器 相当于new 目标对象
Class>[] interfaces,目标对象实现是接口
InvocationHandler h)创建代理对象的回调函数
*
*
* */
Star star=new Star();
Class<? extends Star> aClass = star.getClass();
// 使用cglib进行代理
//其实cglib和jdk比较相似
//使用cglib创建代理对象
//通过这个Enhancer类来去帮助我们创建代理对象
Enhancer enhancer =new Enhancer();
//在newProxyInstance有三个参数,其实enhancer是一样的
enhancer.setClassLoader(aClass.getClassLoader());
enhancer.setInterfaces(aClass.getInterfaces());
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("商家与经纪人沟通");
System.out.println("签合同");
System.out.println("给钱");
/*
* Object obj: 目标对象
* Object... args:参数
*
* */
//Object obj =null;
Object obj=method.invoke(star,objects);
System.out.println("关闭链接");
return obj;
}
});
//这里我们依然去拿代理对象
Skill dailiobj = (Skill) enhancer.create();
System.out.println(dailiobj.getClass());
// Skill dailiobj= (Skill) Proxy.newProxyInstance(aClass.getClassLoader(), aClass.getInterfaces(), new InvocationHandler() {
//这是匿名内部类,回调函数,在jdk8之后出现了lambad表达式
/*
* proxy:代理对象
* method:代理方法
* args:代理参数
* Throwable:异常处理
* */
//代理对象的方法
//说明如果在这里不进行强制类型转换是无法调用sing放方法和dance方法,
dailiobj.sing();
dailiobj.dance();
}
}
interface Skill{
void sing();
void dance();
}
//目标类
class Star implements Skill{
public void sing(){
System.out.println("唱歌好听");
}
public void dance(){
System.out.println("跳舞");
}
}
实测cglib的代理
package com.biyi.action;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Poxy {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Car.class);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy)
throws Throwable {
System.out.println("before");
Object res = methodProxy.invokeSuper(obj, args);
System.out.println("after");
return res;
}
});
Car car = (Car) enhancer.create();
car.print();
}
static class Car {
void print() {
System.out.println("I am a car");
}
}
}
1、一定程度上降低了系统的耦合度,扩展性好。
2、可以起到保护目标对象的作用。
3、可以对目标对象的功能增强。
1,代理模式会造成系统设计中类的数量增加。
2、在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢。
3、增加了系统的复杂度。
在实际开发中,那么就会有很多个目标对象,那么如果每个都需要我们进行创建代理类,这个时候就会出现代码冗余,所以这个时候就需要用到Springaop面向切面编程
1,在Java中是面向对象编程
2,aop是面向切面编程
面向切面编程最主要的特点是:对方法都扩展,并且不改变原代码的情况下;完成该方法的推展
前言:解决的最大的问题就是在三层代码结构中层与层之间的关联,比如耦合行较高的代码冗余,还比如对service层的某个方法的功能增强等这种问题
总结:再不修改代码的情况下,对某个方法的功能的拓展,最简单的例子,比如监控某个方法的所用时长等等这种情况
1,降低模块的耦合度
2,使系统更容易拓展
3,使代码更好的复用性
可以增强的点/方法(就比如我们刚才的新增,更新等方法就是增强的点)
程序执行的某个特定位置,比如(类开始初始化前,初始化后,方法前,方法后,异常后) 一个类或者一段程序代码拥有一些具有边界的特定点,这些特定点称为连接点
真正增强的点,虽然我们有新增,更新,删除但是我们真正需要增强的方法只是其中一个方法
注意⚠️:连接点不一定是切入点
每个程序都拥有多个连接点,比如一个类有2个方法,这2个方法就是连接点,连接点就是程序中具体的事物,AOP 通过切点来定位特定的连接点,连接点相当于数据库中的记录,而切点相当于是查询记录的条件。在程序中,切点是连接点位置的集合
增强的逻辑,也可以说是增强的功能,比如日志管理,权限校验等
就是我们要具体做的事情,也就在原有的方法之上添加新的能力
目标对象:就是我们要增强的类;
引入:特殊的增强,为类添加属性和方法。哪怕这个类没有任何的属性和方法我们也可以通过aop去添加方法和属性实现逻辑
被代理的对象,增强谁的方法,这个类就是目标对象
一个类被AOP织入增强后产生的结果类,他是原类和增强后的代理类,更具代理s不同的方式,代理类可能是和原类具有相同接口的类,也可能是原类的子类
aop其实就是面向切面编程,切面其实就是我们对方法功能的拓展的类
切面由切点和增强组成,他既包含横切的定义,也包括了连接点的定义,spring aop就是负责实施切面的框架,他将切面定义为横切逻辑织入到切面所指定的连接点
在pom.xml文件中引入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.biyi</groupId>
<artifactId>spring_3</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
</properties>
<dependencies>
<!--spring的上下文依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.9</version>
</dependency>
<!--aop的核心包-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.9.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.9</version>
</dependency>
</dependencies>
</project>
需求实现service逻辑的业务的增强(事务的管理)
其余的代码为三层代码结构的代码
创建切面类
package com.biyi.aspect;
import org.aopalliance.intercept.Invocation;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import java.lang.reflect.Method;
//编写切面类,这个类就是代理类
//当我们编写这个是一个普通类所以我们要实现
//MethodInterceptor这是aop包里面的接口,不要引错了
@Component
public class MyAspect implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation Invocation) throws Throwable {
//在这里编写增强/通知(业务逻辑)
System.out.println("开启事务");
//在这里我们是不是需要写我们的链接点,哪些方法需要增强,其实谁是方法,这里的在这里Invocation.getMethod()执行目标对象的业务功能,在这里增强方法
//通过MethodInvocation就可以拿到对象即可getMethod
//然后我们要进行切入点,在这里我们要拿到可以增强的方法,
Method method = Invocation.getMethod();
//执行方法,之前都是通过method.invoke这个方法执行,但是在aop里面是拿不到这个方法,但是,在aop里面封装了一个proceed这个方法进行
//具体如何拿到需要增强的方法,我们之前都是通过invoke,但是在aop里面我们是拿不到这个方法的,但是底层给我们封装了proceed这个方法
Object obj = Invocation.proceed();
System.out.println("提交事务");
return obj;
}
}
编写aop代理类的代码之后要告诉我对谁增强,那么就用到了aop的配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="com.biyi"/>
<!--配置aop,指定那些类的哪些方法需要被增强
那么这个有规则
id的值是ID的名称,
expression:表达式 1, within 粗粒度 也就是说只能定位到类上 2,excution是相对来说叫细粒度,可以定位到某个方法的
* com.biyi.service.*.*(..)其中*标示所有这句话说明在com.biyi.service包下的所有方法增强
<aop:config proxy-target-class="true">
proxy-target-class="true"jdk代理
proxy-target-class="false"。cglib代理
但是我们一般不写
-->
<aop:config >
<aop:pointcut id="point" expression="execution(* com.biyi.service.*.*(..))"/>
<aop:pointcut id="point" expression="within(com.biyi.service.*)"/><!--关于within的使用由于只能定位到类上所以后面到不能使用-->
<!--增强什么样的逻辑,也就是我们写的切面,切面类放到容器,在这里引用-->
<!--配置通知-->
<aop:advisor advice-ref="myAspect" pointcut-ref="point"/>
</aop:config>
</beans>
package com.biyi.admintest;
import com.biyi.controller.UserController;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:springconfig.xml")
public class AdminTest {
@Autowired
private UserController userController;
public void fun1(){
userController.addUser();
System.out.println();
}
}
其余的代码为三层代码结构
代码的复用性
其余的就是三层代码结构
下面的这是测试类的代码
在上面的情况是都执行了一遍,但是有时候只需要部分执行,
比如
在方法执行之前执行,在方法执行之后执行,有时候在方法前后进行管理,那么这种情况就需要用到通知
但是如果我们都将这种通知,写到代理对象中就会出现代码冗余,耦合性高这种情况
aop的5大通知
前置通知
后置通知
环绕通知
最终通知
异常通知
package com.biyi.aspect;
import org.springframework.stereotype.Component;
@Component
public class MySecond {
public void a(){
System.out.println("前置通知before");
}
}
前置通知
在springconfig文件里面
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="com.biyi"/>
<!-- <aop:config>
<aop:pointcut id="point" expression="execution(* com.biyi.service.*.*(..))"/>
<aop:pointcut id="point" expression="within(com.biyi.service.*)"/>由于只能定位到类上所以后面到不能使用–>
<aop:advisor advice-ref="myAspect" pointcut-ref="point"/>
</aop:config>-->
<!--Spring的6大通知
前置通知(就是业务执行之前进行使用),比如权限校验
后置通知(就是业务执行之前进行使用),比如日志管理
环绕通知(就是业务执行之前后进行使用)某个方法执行的时间等
最终通知(方法执行结束之后进行使用)
异常通知就是在方法中出现之后有异常出现进行使用
引介通知
-->
<aop:config>
<!--对于service是开启事务-->
<aop:pointcut id="point1" expression="execution(* com.biyi.service.*.*(..))"/>
<!--对于dao是日志管理-->
<aop:pointcut id="point2" expression="execution(* com.biyi.dao.*.*(..))"/>
<!--使用Spring到通知进行增强-->
<aop:aspect ref="mySecond">
<aop:before method="a" pointcut-ref="point1"/>
</aop:aspect>
</aop:config>
</beans>
创建新的代理类
package com.biyi.aspect;
import org.springframework.stereotype.Component;
@Component
public class MySecond {
public void a(){
System.out.println("前置通知before");
}
}
执行结果
后置通知
配置类
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="com.biyi"/>
<!-- <aop:config>
<!– <aop:pointcut id="point" expression="execution(* com.biyi.service.*.*(..))"/>–>
<aop:pointcut id="point" expression="within(com.biyi.service.*)"/><!–由于只能定位到类上所以后面到不能使用–>
<aop:advisor advice-ref="myAspect" pointcut-ref="point"/>
</aop:config>-->
<!--Spring的6大通知
前置通知(就是业务执行之前进行使用),比如权限校验
后置通知(就是业务执行之前进行使用),比如日志管理
环绕通知(就是业务执行之前后进行使用)某个方法执行的时间等
最终通知(方法执行结束之后进行使用)
异常通知就是在方法中出现之后有异常出现进行使用
引介通知
-->
<aop:config>
<!--对于service是开启事务-->
<aop:pointcut id="point1" expression="execution(* com.biyi.service.*.*(..))"/>
<!--对于dao是日志管理-->
<aop:pointcut id="point2" expression="execution(* com.biyi.dao.*.*(..))"/>
<!--使用Spring到通知进行增强-->
<aop:aspect ref="mySecond">
<aop:before method="a" pointcut-ref="point1"/>
<aop:after method="after" pointcut-ref="point2"/>
</aop:aspect>
</aop:config>
</beans>
代理类
package com.biyi.aspect;
import org.springframework.stereotype.Component;
@Component
public class MySecond {
public void a(){
System.out.println("前置通知before");
}
public void after(){
System.out.println("后置通知after");
}
}
环绕通知和异常通知
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="com.biyi"/>
<!-- <aop:config>
<!– <aop:pointcut id="point" expression="execution(* com.biyi.service.*.*(..))"/>–>
<aop:pointcut id="point" expression="within(com.biyi.service.*)"/><!–由于只能定位到类上所以后面到不能使用–>
<aop:advisor advice-ref="myAspect" pointcut-ref="point"/>
</aop:config>-->
<!--Spring的6大通知
前置通知(就是业务执行之前进行使用),比如权限校验
后置通知(就是业务执行之前进行使用),比如日志管理
环绕通知(就是业务执行之前后进行使用)某个方法执行的时间等
最终通知(方法执行结束之后进行使用)
异常通知就是在方法中出现之后有异常出现进行使用
引介通知
-->
<aop:config>
<!--对于service是开启事务-->
<aop:pointcut id="point1" expression="execution(* com.biyi.service.*.*(..))"/>
<!--对于dao是日志管理-->
<aop:pointcut id="point2" expression="execution(* com.biyi.dao.*.*(..))"/>
<!--使用Spring到通知进行增强-->
<aop:aspect ref="mySecond">
<aop:before method="a" pointcut-ref="point1"/>
<aop:after method="after" pointcut-ref="point2"/>
<aop:around method="around" pointcut-ref="point1"/>
<aop:after-returning method="afterreturning" pointcut-ref="point1"/>
<aop:after-throwing method="afterthrow" pointcut-ref="point1" throwing="e"/>
</aop:aspect>
</aop:config>
</beans>
代理类
package com.biyi.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.stereotype.Component;
@Component
public class MySecond {
public void a(){
System.out.println("前置通知before");
}
public void after(){
System.out.println("后置通知after");
}
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("方法执行前");
Object obj = joinPoint.proceed();
System.out.println("方法执行后");
return obj;
}
public void afterreturning(){
System.out.println("最终通知");
}
public void afterthrow(Exception e){
//注意:这个throw是只有异常才能执行,否则不执行,比如在service里面System.out.println(1/0)执行就会执行这个异常
System.out.println(1/0);
}
}
package com.biyi.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.stereotype.Component;
@Component
public class MySecond {
public void a(){
System.out.println("前置通知before");
}
public void after(){
System.out.println("后置通知after");
}
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("方法执行前");
Object obj = joinPoint.proceed();
System.out.println("方法执行后");
return obj;
}
public void afterreturning(){
System.out.println("最终通知");
}
public void afterthrow(Exception e){
//注意:这个throw是只有异常才能执行,否则不执行,比如在service里面System.out.println(1/0)执行就会执行这个异常
System.out.println("throwing");
}
}
package com.biyi.aspect;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Component
@Aspect//标示这个类就是一个切面类
public class MyThird {
@Pointcut("execution(* com.biyi.service.*.*(..))")
public void print1(){}
@Before("print1()")
public void before(){
System.out.println("这是前置通知");
}
@After("print1()")
public void after(){
System.out.println("后置通知after");
}
@Around("print1()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("方法执行前");
Object obj = joinPoint.proceed();
System.out.println("方法执行后");
return obj;
}
@AfterReturning("print1()")
public void afterreturning(){
System.out.println("最终通知");
}
@afterthrowing("print1()")
public void afterthrow(){
//注意:这个throw是只有异常才能执行,否则不执行,比如在service里面System.out.println(1/0)执行就会执行这个异常
System.out.println("throwing");
}
}
在配置类里面添加开启aop注解驱动
<!--开启aop的驱动-->
<aop:aspectj-autoproxy/>