FactoryBean是一个Factory对象,用于生成其他bean示例。当一个bean实现FactoryBean接口后,Spring容器调用其getObject方法返回该工厂所生成的bean,而不是该FactoryBean本身。但是工厂生成的产品对象只能说是一部分受到Spring容器的管理,我们来看看下面的例子:
我们把一个Bean1通过工厂Bean的方法纳入Spring管理,看看结果:
Bean1:
public class Bean1 implements BeanFactoryAware {
private static final Logger log = LoggerFactory.getLogger(Bean1.class);
private Bean2 bean2;
@Autowired
public void setBean2(Bean2 bean2) {
log.debug("setBean2({})", bean2);
this.bean2 = bean2;
}
public Bean2 getBean2() {
return bean2;
}
@PostConstruct
public void init() {
log.debug("init");
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
log.debug("setBeanFactory({})", beanFactory);
}
}
Bean1的工厂类:
@Component("bean1")
public class Bean1FactoryBean implements FactoryBean<Bean1> {
private static final Logger log = LoggerFactory.getLogger(Bean1FactoryBean.class);
// 决定了根据【类型】获取或依赖注入能否成功
@Override
public Class<?> getObjectType() {
return Bean1.class;
}
// 决定了 getObject() 方法被调用一次还是多次
@Override
public boolean isSingleton() {
return true;
}
@Override
public Bean1 getObject() throws Exception {
Bean1 bean1 = new Bean1();
log.debug("create bean: {}", bean1);
return bean1;
}
}
Bean后处理器:
@Component
public class Bean1PostProcessor implements BeanPostProcessor {
private static final Logger log = LoggerFactory.getLogger(Bean1PostProcessor.class);
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("bean1") && bean instanceof Bean1) {
log.debug("before [{}] init", beanName);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("bean1") && bean instanceof Bean1) {
log.debug("after [{}] init", beanName);
}
return bean;
}
}
测试类:
@ComponentScan
public class A43 {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(A43.class);
Bean1 bean1 = (Bean1) context.getBean("bean1");
Bean1 bean2 = (Bean1) context.getBean("bean1");
Bean1 bean3 = (Bean1) context.getBean("bean1");
//因为工厂isSingleton方法返回的true,所以是单例模式
System.out.println(bean1);
System.out.println(bean2);
System.out.println(bean3);
//如果想通过类型获取,那么工厂中的getObjectType方法就一定要返回正确的值
System.out.println(context.getBean(Bean1.class));
//两种获取工厂bean的方法
System.out.println(context.getBean(Bean1FactoryBean.class));
System.out.println(context.getBean("&bean1"));
context.close();
}
结果:
总结:
我们看一段代码:
@Component
public class Bean1 {
private static final Logger log = LoggerFactory.getLogger(Bean1.class);
protected Bean2 bean2;
protected boolean initialized;
@Autowired
public void setBean2(Bean2 bean2) {
log.debug("setBean2(Bean2 bean2)");
this.bean2 = bean2;
}
@PostConstruct
public void init() {
log.debug("init");
initialized = true;
}
public Bean2 getBean2() {
log.debug("getBean2()");
return bean2;
}
public boolean isInitialized() {
log.debug("isInitialized()");
return initialized;
}
}
增强:
@Aspect
@Component
public class MyAspect {
// 故意对所有方法增强
@Before("execution(* com.itheima.a45.Bean1.*(..))")
public void before() {
System.out.println("before");
}
}
从这里我们可以看出来依赖注入和初始化影响的是原始对象
我们再来看看代理与目标的成员变量情况:
public static void showProxyAndTarget(Bean1 proxy) throws Exception {
System.out.println(">>>>> 代理中的成员变量");
System.out.println("\tinitialized=" + proxy.initialized);
System.out.println("\tbean2=" + proxy.bean2);
if (proxy instanceof Advised advised) {
System.out.println(">>>>> 目标中的成员变量");
Bean1 target = (Bean1) advised.getTargetSource().getTarget();
System.out.println("\tinitialized=" + target.initialized);
System.out.println("\tbean2=" + target.bean2);
}
}
所以说代理与目标是两个对象,二者成员变量并不共用数据。我们平时是使用的方法去获取成员变量,方法虽然被增强,但其中还是会调用原方法,所以获取的就是目标对象中的成员变量。这也给我们一种提示我们想要走代理增强就必须走方法,不能走成员。
spring 代理的设计特点
依赖注入和初始化影响的是原始对象
代理与目标是两个对象,二者成员变量并不共用数据
static 方法、final 方法、private 方法均无法增强
示例代码:
@Configuration
@SuppressWarnings("all")
public class A46 {
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(A46.class);
DefaultListableBeanFactory beanFactory = context.getDefaultListableBeanFactory();
ContextAnnotationAutowireCandidateResolver resolver = new ContextAnnotationAutowireCandidateResolver();
resolver.setBeanFactory(beanFactory);
// test1(context, resolver, Bean1.class.getDeclaredField("home"));
// test2(context, resolver, Bean1.class.getDeclaredField("age"));
// test3(context, resolver, Bean2.class.getDeclaredField("bean3"));
test3(context, resolver, Bean4.class.getDeclaredField("value"));
}
private static void test3(AnnotationConfigApplicationContext context, ContextAnnotationAutowireCandidateResolver resolver, Field field) {
DependencyDescriptor dd1 = new DependencyDescriptor(field, false);
// 获取 @Value 的内容
String value = resolver.getSuggestedValue(dd1).toString();
System.out.println(value);
// 解析 ${}
value = context.getEnvironment().resolvePlaceholders(value);
System.out.println(value);
System.out.println(value.getClass());
// 解析 #{} @bean3
Object bean3 = context.getBeanFactory().getBeanExpressionResolver().evaluate(value, new BeanExpressionContext(context.getBeanFactory(), null));
// 类型转换
Object result = context.getBeanFactory().getTypeConverter().convertIfNecessary(bean3, dd1.getDependencyType());
System.out.println(result);
}
private static void test2(AnnotationConfigApplicationContext context, ContextAnnotationAutowireCandidateResolver resolver, Field field) {
DependencyDescriptor dd1 = new DependencyDescriptor(field, false);
// 获取 @Value 的内容
String value = resolver.getSuggestedValue(dd1).toString();
System.out.println(value);
// 解析 ${}
value = context.getEnvironment().resolvePlaceholders(value);
System.out.println(value);
System.out.println(value.getClass());
Object age = context.getBeanFactory().getTypeConverter().convertIfNecessary(value, dd1.getDependencyType());
System.out.println(age.getClass());
}
private static void test1(AnnotationConfigApplicationContext context, ContextAnnotationAutowireCandidateResolver resolver, Field field) {
DependencyDescriptor dd1 = new DependencyDescriptor(field, false);
// 获取 @Value 的内容
String value = resolver.getSuggestedValue(dd1).toString();
System.out.println(value);
// 解析 ${}
value = context.getEnvironment().resolvePlaceholders(value);
System.out.println(value);
}
public class Bean1 {
@Value("${JAVA_HOME}")
private String home;
@Value("18")
private int age;
}
public class Bean2 {
@Value("#{@bean3}") // SpringEL #{SpEL}
private Bean3 bean3;
}
@Component("bean3")
public class Bean3 {
}
static class Bean4 {
@Value("#{'hello, ' + '${JAVA_HOME}'}")
private String value;
}
}
重点:
收获
事件监听器的两种方式
示例代码:
实现 ApplicationListener 接口:
// 事件解耦例子
@Configuration
public class A48_1 {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(A48_1.class);
context.getBean(MyService.class).doBusiness();
context.close();
}
static class MyEvent extends ApplicationEvent {
public MyEvent(Object source) {
super(source);
}
}
@Component
static class MyService {
private static final Logger log = LoggerFactory.getLogger(MyService.class);
@Autowired
private ApplicationEventPublisher publisher; // applicationContext
public void doBusiness() {
log.debug("主线业务");
// 主线业务完成后需要做一些支线业务,下面是问题代码
publisher.publishEvent(new MyEvent("MyService.doBusiness()"));
}
}
@Component
static class SmsApplicationListener implements ApplicationListener<MyEvent> {
private static final Logger log = LoggerFactory.getLogger(SmsApplicationListener.class);
@Override
public void onApplicationEvent(MyEvent event) {
log.debug("发送短信");
}
}
@Component
static class EmailApplicationListener implements ApplicationListener<MyEvent> {
private static final Logger log = LoggerFactory.getLogger(EmailApplicationListener.class);
@Override
public void onApplicationEvent(MyEvent event) {
log.debug("发送邮件");
}
}
}
使用@EventListener:
@Configuration
public class A48_2 {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(A48_2.class);
context.getBean(MyService.class).doBusiness();
context.close();
}
static class MyEvent extends ApplicationEvent {
public MyEvent(Object source) {
super(source);
}
}
@Component
static class MyService {
private static final Logger log = LoggerFactory.getLogger(MyService.class);
@Autowired
private ApplicationEventPublisher publisher; // applicationContext
public void doBusiness() {
log.debug("主线业务");
// 主线业务完成后需要做一些支线业务,下面是问题代码
publisher.publishEvent(new MyEvent("MyService.doBusiness()"));
}
}
@Component
static class SmsService {
private static final Logger log = LoggerFactory.getLogger(SmsService.class);
@EventListener
public void listener(MyEvent myEvent) {
log.debug("发送短信");
}
}
@Component
static class EmailService {
private static final Logger log = LoggerFactory.getLogger(EmailService.class);
@EventListener
public void listener(MyEvent myEvent) {
log.debug("发送邮件");
}
}
//模拟多线程
@Bean
public ThreadPoolTaskExecutor executor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(3);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(100);
return executor;
}
@Bean
public SimpleApplicationEventMulticaster applicationEventMulticaster(ThreadPoolTaskExecutor executor) {
SimpleApplicationEventMulticaster multicaster = new SimpleApplicationEventMulticaster();
multicaster.setTaskExecutor(executor);
return multicaster;
}
}
@Bean
public ApplicationEventMulticaster applicationEventMulticaster(ConfigurableApplicationContext context, ThreadPoolTaskExecutor executor) {
return new AbstractApplicationEventMulticaster() {
private List<GenericApplicationListener> listeners = new ArrayList<>();
// 收集监听器
public void addApplicationListenerBean(String name) {
ApplicationListener listener = context.getBean(name, ApplicationListener.class);
System.out.println(listener);
// 获取该监听器支持的事件类型
ResolvableType type = ResolvableType.forClass(listener.getClass()).getInterfaces()[0].getGeneric();
System.out.println(type);
// 将原始的 listener 封装为支持事件类型检查的 listener
GenericApplicationListener genericApplicationListener = new GenericApplicationListener() {
// 是否支持某事件类型 真实的事件类型
public boolean supportsEventType(ResolvableType eventType) {
return type.isAssignableFrom(eventType);
}
public void onApplicationEvent(ApplicationEvent event) {
executor.submit(() -> listener.onApplicationEvent(event));
}
};
listeners.add(genericApplicationListener);
}
// 发布事件
public void multicastEvent(ApplicationEvent event, ResolvableType eventType) {
for (GenericApplicationListener listener : listeners) {
if (listener.supportsEventType(ResolvableType.forClass(event.getClass()))) {
listener.onApplicationEvent(event);
}
}
}
};
}
为了只实现两个核心方法,我们创建了一个AbstractApplicationEventMulticaster对ApplicationEventMulticaster接口进行了空实现,并定义为抽象类:
事件发布器模拟实现