闽公网安备 35020302035485号
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;
}
}
解释