Spring AOP(Aspect-Oriented Programming,面向切面编程)是Spring框架中的一个重要模块,它允许开发者通过切面(Aspect)来实现横切关注点(Cross-cutting Concerns),如事务管理、日志记录、安全等。而TargetSource是Spring AOP中的一个接口,用于确定AOP代理的目标对象(或称为目标Bean)。
public interface TargetSource { Class<?> getTargetClass(); boolean isStatic(); Object getTarget() throws Exception; void releaseTarget(Object target) throws Exception; }方法解析
例如,如果代理的是一个UserService对象,这个方法会返回UserService.class。
返回一个布尔值,指示目标对象是否是静态的。如果目标对象是静态的(即每次调用都返回同一个实例),返回true;否则返回false。
每次调用getTarget()时返回一个新的目标对象实例,适用于目标对象是原型(Prototype)作用域的情况。
为每个线程提供一个独立的目标对象实例,使用ThreadLocal来存储目标对象。
import org.springframework.aop.TargetSource; import org.springframework.aop.framework.ProxyFactory; import org.springframework.aop.target.SingletonTargetSource; public class TargetSourceExample { public static void main(String[] args) { // 创建目标对象 MyService target = new MyService(); // 堆代码 duidaima.com // 创建SingletonTargetSource TargetSource targetSource = new SingletonTargetSource(target); // 创建代理工厂 ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.setTargetSource(targetSource); // 获取代理对象 MyService proxy = (MyService) proxyFactory.getProxy(); // 调用代理对象的方法 proxy.doSomething(); } } class MyService { public void doSomething() { System.out.println("Doing something..."); } }
在这个示例中,SingletonTargetSource确保每次调用代理对象的方法时都会使用同一个MyService实例。
import org.springframework.aop.framework.ProxyFactory; import org.springframework.aop.target.HotSwappableTargetSource; public class HotSwappableTargetSourceExample { public static void main(String[] args) { // 创建原始目标对象 MyService originalService = new MyServiceImpl1(); // 创建HotSwappableTargetSource并设置初始目标对象 HotSwappableTargetSource hotSwappableTargetSource = new HotSwappableTargetSource(originalService); // 创建代理工厂并设置TargetSource ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.setTargetSource(hotSwappableTargetSource); // 获取代理对象 MyService proxy = (MyService) proxyFactory.getProxy(); // 调用代理对象的方法,使用原始目标对象 proxy.doSomething(); // 创建新的目标对象 MyService newService = new MyServiceImpl2(); // 动态替换目标对象 hotSwappableTargetSource.swap(newService); // 获取新的代理对象 MyServiceInterface proxy2 = (MyServiceInterface) proxyFactory.getProxy(); // 调用代理对象的方法,使用新的目标对象 proxy2.doSomething(); } } interface MyService { void doSomething(); } class MyServiceImpl1 implements MyService { @Override public void doSomething() { System.out.println("MyServiceImpl1 is doing something..."); } } class MyServiceImpl2 implements MyService { @Override public void doSomething() { System.out.println("MyServiceImpl2 is doing something..."); } }解释
通过这种方式,可以在运行时动态地替换目标对象,而无需重新创建代理对象或重启应用程序。这对于需要高可用性和动态更新的应用场景非常有用。
public class CommonsPool2TargetSourceExample { public static void main(String[] args) { // 使用 Spring 上下文加载配置 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); // 获取代理对象 MyServiceInterface2 proxy = (MyServiceInterface2) context.getBean("myServiceProxy"); // 调用代理对象的方法 for (int i = 0; i < 10; i++) { proxy.doSomething(); } // 关闭上下文 context.close(); } } @Configuration class AppConfig { @Bean public CommonsPool2TargetSource commonsPool2TargetSource() { CommonsPool2TargetSource targetSource = new CommonsPool2TargetSource(); targetSource.setTargetBeanName("myService"); targetSource.setMaxSize(5); // 设置池中最大对象数 return targetSource; } @Bean @Scope("prototype") public MyServiceInterface2 myService() { // 此处应该是实例化比较消耗的资源的Bean return new MyServiceImpl(); } @Bean public MyServiceInterface2 myServiceProxy(CommonsPool2TargetSource commonsPool2TargetSource) { ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.setTargetSource(commonsPool2TargetSource); return (MyServiceInterface2) proxyFactory.getProxy(); } } // 目标对象接口 interface MyServiceInterface2 { void doSomething(); } // 目标对象实现 class MyServiceImpl implements MyServiceInterface2 { @Override public void doSomething() { System.out.println("MyServiceImpl is doing something..."); } }ThreadLocalTargetSource示例
public class ThreadLocalTargetSourceExample { public static void main(String[] args) { // 使用 Spring 上下文加载配置 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig3.class); // 获取代理对象 MyServiceInterface3 proxy = (MyServiceInterface3) context.getBean("myServiceProxy"); // 创建多个线程,验证每个线程有独立的目标对象实例 Runnable task = () -> { System.out.println(Thread.currentThread().getName() + ": " + proxy.doSomething()); }; Thread thread1 = new Thread(task, "Thread-1"); Thread thread2 = new Thread(task, "Thread-2"); thread1.start(); thread2.start(); // 等待线程执行完毕 try { thread1.join(); thread2.join(); } catch (InterruptedException e) { e.printStackTrace(); } // 关闭上下文 context.close(); } } @Configuration class AppConfig3 { @Bean public ThreadLocalTargetSource threadLocalTargetSource() { ThreadLocalTargetSource targetSource = new ThreadLocalTargetSource(); targetSource.setTargetBeanName("myService"); targetSource.setTargetClass(MyServiceInterface3.class); return targetSource; } @Bean @Scope("prototype") public MyServiceInterface3 myService() { return new MyServiceImpl3(); } @Bean public MyServiceInterface3 myServiceProxy(ThreadLocalTargetSource threadLocalTargetSource) { ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.setTargetSource(threadLocalTargetSource); proxyFactory.setInterfaces(MyServiceInterface3.class); // 设置代理接口 return (MyServiceInterface3) proxyFactory.getProxy(); } } // 目标对象接口 interface MyServiceInterface3 { String doSomething(); } // 目标对象实现 class MyServiceImpl3 implements MyServiceInterface3 { private final String instanceId; public MyServiceImpl3() { this.instanceId = "Instance-" + System.currentTimeMillis(); } @Override public String doSomething() { return "MyServiceImpl is doing something with " + instanceId; } }解释