1、具体代码
package com.xch.proxy;
/**
* 具体业务接口
*
* @author XuChenghe
* @date 2023/8/18 15:09
*/
public interface Star {
/**
* 唱歌方法
*
* @param name
* @return
*/
String sing(String name);
/**
* 跳舞方法
*/
void dance();
}
package com.xch.proxy;
/**
* 具体业务实现类
*
* @author XuChenghe
* @date 2023/8/18 15:06
*/
public class BigStar implements Star {
private String userName;
public BigStar(String userName) {
this.userName = userName;
}
/**
* {@inheritDoc}
*/
public String sing(String songName) {
System.out.println(this.userName + "正在唱:" + songName);
return "谢谢!谢谢!";
}
/**
* {@inheritDoc}
*/
public void dance() {
System.out.println(this.userName + "正在优美的跳舞~~");
}
}
package com.xch.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 动态代理的工具类(产生代理的)
* -手动实现原生动态代理
*
* @author XuChenghe
* @date 2023/8/18 15:11
*/
public class ProxyUtil {
public static Star createProxy(BigStar bigStar) {
// 参数1:ClassLoader用于指定一个类加载器
// 参数2:指定生成的代理有哪些方法
// 参数3:用来指定生成的代理对象要干什么事情(动态代理的核心)
Star starProxy = (Star) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(),
new Class[]{Star.class}, new InvocationHandler() {
// 回调方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 动态代理要做的事情,会在这里写代码
if ("sing".equals(method.getName())) {
System.out.println("准备话筒,收钱20万");
} else if ("dance".equals(method.getName())) {
System.out.println("准备场地,收钱100万");
}
return method.invoke(bigStar, args);
}
}
);
return starProxy;
}
}
package com.xch.proxy;
/**
* 运行启动测试类
*
* @author XuChenghe
* @date 2023/8/18 15:21
*/
public class LaunchTest {
public static void main(String[] args) {
Star starProxy = ProxyUtil.createProxy(new BigStar("杨超越"));
String result = starProxy.sing("好日子");
System.out.println(result);
starProxy.dance();
}
}
1、pom文件依赖
org.springframework.boot
spring-boot-starter-aop
org.springframework
spring-tx
2、具体代码
package com.xch.proxy_product;
/**
* 具体业务接口
*
* @author XuChenghe
* @date 2023/8/18 15:09
*/
public interface Star {
/**
* 实际生产中使用的代理调用
*
* @param name
* @return
*/
String proxySing(String name);
/**
* 实际生产中使用的代理调用
*/
void proxyDance();
}
package com.xch.proxy_product;
import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* 具体业务实现类
*
* @author XuChenghe
* @date 2023/8/18 15:06
*/
@Service
public class BigStar implements Star {
/**
* 唱歌方法
*
* @param songName
* @return
*/
@Transactional(rollbackFor = Exception.class)
public String sing(String songName) {
System.out.println("杨超越正在唱:" + songName);
return "谢谢!谢谢!";
}
/**
* 跳舞方法
*/
@Transactional(rollbackFor = Exception.class)
public void dance() {
System.out.println("杨超越正在优美的跳舞~~");
}
/**
* {@inheritDoc}
*/
@Transactional(rollbackFor = Exception.class)
public String proxySing(String songName) {
System.out.println("准备话筒,收钱20万");
return getCurrentProxy().sing("好日子");
}
/**
* {@inheritDoc}
*/
@Transactional(rollbackFor = Exception.class)
public void proxyDance() {
System.out.println("准备场地,收钱100万");
getCurrentProxy().dance();
}
/**
* 获取当前类的代理
*
* @return 当前类的代理
*/
private static BigStar getCurrentProxy() {
return (BigStar) AopContext.currentProxy();
}
}
package com.xch.proxy_product;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
/**
* 通用业务的切面类
*
* @author XuChenghe
* @date 2023/8/20 8:55
*/
@Aspect // 声明该类的作用:切面类
@Component // 等价于@Configuration:交由Spring的IOC容器管理
public class BigStarAspect {
/**
* 定义公共切入点
* -假设proxy_product是service业务层包
* -则通过以下表达式匹配该业务包下的所有子孙类的所有public修饰的方法
*
* 另外,配置的切入表达式必须是符合public修饰的方法
* 因为,Spring事务即AOP的底层通过动态代理生成代理调用该方法时,
* 会判断方法只能是public修饰的Modifier.isPublic(method.getModifiers())
*/
@Pointcut("execution(public * com.xch.proxy_product..*(..))")
public void myPointcut() {
// 公共切入点
}
/**
* 配置切面方法(环绕通知):方法增强
*
* @param pjp 连接点:当前切入方法的信息
* @return 方法执行的返回结果
* @throws Throwable 方法执行时抛出的异常
*/
@Around("myPointcut()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("=====环绕通知(开始)=====");
// 前置增强代码
Object proceed = pjp.proceed();
// 后置/返回增强代码
// 最终增强代码
// 抛出异常后增强代码
System.out.println("=====环绕通知(结束)=====");
return proceed;
}
}
package com.xch;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
/**
* 启用Spring的动态代理,默认使用JDK动态代理(由proxyTargetClass控制)
*/
@SpringBootApplication
@EnableAspectJAutoProxy(exposeProxy = true)
public class SubDynamicProxyApplication {
public static void main(String[] args) {
SpringApplication.run(SubDynamicProxyApplication.class, args);
}
}
package com.xch.proxy_product;
import org.junit.jupiter.api.Test;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
/**
* 运行启动测试类
*
* @author XuChenghe
* @date 2023/8/18 15:21
*/
@SpringBootTest
public class LaunchTest {
@Autowired
private Star star;
@Test
public void launch() {
String result = star.proxySing("好日子");
System.out.println(result);
System.out.println();
star.proxyDance();
// 判断该注入类是否代理类
// -Spring的IOC容器中默认都是原生对象
// -只有配置了AOP增强的对象才是代理对象
System.out.println(AopUtils.isAopProxy(star));
}
}