注解管理Bean
这部分内容来自我的博客文章 《Spring:IOC之基于注解管理》
注解只是一个标记,作用是框架检测到注解标记的位置,然后针对这个位置按照注解标记的功能来执行具体操作。
要实现基于注解来管理bean,要先创建组件、再扫描组件,
通过注解+扫描,就可以将扫描的包下加上注解的类作为组件作为管理(其实就是在IOC容器内有了加上注解的这个类所对应的bean对象)
以下面这个例子为例 :
创建组件
创建控制层组件
1 2 3
| @Controller public class UserController { }
|
扫描组件
扫描组件在配置文件中进行扫描,目的在于让Spring知道哪些类加了什么注解。
使用的标签是<context:component-scan>
,扫描的包通过 base-package
字段指定。
分为三种情况 : 最基本的扫描方式、指定要排除的方式、指定要扫描的方式
最基本的扫描
1 2 3
| XML <context:component-scan base-package="com.atguigu"> </context:component-scan>
|
基于注解的自动装配
基于注解的自动装配使用 @Autowired
注解实现。只需要在成员变量上添加 @Autowired
注解即可 :
注意 : 使用了该注解之后就不需要再写setter和getter方法了。
在基于xml管理bean的环节中,自动装配的方法是在配置文件中使用autowire字段
1 2 3 4 5 6 7
| JAVA @Controller public class UserController { @Autowired private UserService userService; ... }
|
而@Autowired的原理,其实就是通过 byType
方式或 byName
的方式来实现自动装配的效果。
实现@Autowired
测试文件
这是我们要实现的目标。写一个 annotationTest.xml 与 AnnotationBaseService.java ,分别为 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <?xml version="1.0" encoding="UTF-8" ?> <beans> <bean id="bbs" class="com.minis.test.BaseBaseService"> <property type="com.minis.test.AServiceImpl" name="as" ref="aservice" /> </bean> <bean id="aservice" class="com.minis.test.AServiceImpl"> <constructor-arg type="String" name="name" value="abc"/> <constructor-arg type="int" name="level" value="3"/> <property type="String" name="property1" value="Someone says"/> <property type="String" name="property2" value="Hello World!"/> <property type="com.minis.test.BaseService" name="ref1" ref="baseservice"/> </bean> <bean id="baseservice" class="com.minis.test.BaseService">
</bean> </beans>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package com.minis.test;
import com.minis.beans.factory.annotation.Autowired; public class BaseService { @Autowired private BaseBaseService bbs; public BaseBaseService getBbs() { return bbs; } public void setBbs(BaseBaseService bbs) { this.bbs = bbs; } public BaseService() { } public void sayHello() { System.out.println("Base Service says Hello"); bbs.sayHello(); } }
|
可以看到,在上面的测试文件中,给BaseService中依赖的BaseBaseService添加上了 @Autowired
注解,而在xml文件中并没有给BaseService添加上BaseBaseService的ref标签,这样一来想要实现程序,就是我们要实现的自动装配功能( @Autowired )。
解释注解
1 2
| @Autowired private BaseBaseService bbs;
|
注意,这个注解是添加在对象的实例域上的。
因此我们如果想解释这个注解,那么至少应该要等到这个对象创建好。
回顾一下bean创建的流程 :
- 读取xml配置文件,通过ClassPathXmlResource解析xml文件中的内容得到resource
- 定义一个SimpleBeanFactory类型的BeanFactory变量,并且把它赋给XmlBeanDefinitionReader,得到reader
- reader通过loadBeanDefinitions(resource)方法,把resource中的内容转化成我们需要的BeanDefinition并注册
- 以上完成了xml文件中的bean注册(但未生成bean实例)
- 在使用时,直接通过ClassPathXmlApplicationContext的getBean(beanName)方法获取
- getBean(beanName)方法在SimpleBeanFactory中实现,是一个三级缓存结构。如果没有实例且没有早期胚胎,则调用createBean(beanDefinition)创建单例bean。
- createBean(beanDefinition)中会先创造早期胚胎、再注入依赖,总之会返回一个bean实例
- 新注册这个bean实例 ,this.registerSingleton(beanName, singleton);
- 可以获取这个bean的值并使用其中的方法了。
因此我们解读注解的时机,就在7-8之间。而 refresh() 方法 ,是一个包装了整个 Bean 的创建过程,会调用getBean()方法,看一下getBean方法 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| public Object getBean(String beanName) throws BeansException { Object singleton = this.getSingleton(beanName); if (singleton == null) { singleton = this.earlySingletonObjects.get(beanName); if (singleton == null) { BeanDefinition beanDefinition = beanDefinitionMap.get(beanName); singleton = createBean(beanDefinition); this.registerSingleton(beanName, singleton);
} return singleton; } if (singleton == null){ throw new BeansException("bean is null"); } return singleton;
}
|
要处理注解,则创建一个新的接口类 BeanPostProcessor
,这个接口类里面 包含了两个方法,分别是在Bean初始化之前和Bean初始化之后,将这个接口类放入 config
文件夹中。具体如下 :
1 2 3 4 5 6 7 8 9 10 11
| package com.minis.beans.factory.config;
import com.minis.beans.BeansException;
public interface BeanPostProcessor { Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
|
接着,定义好 @Autowired注解。这里定义的方式是在 autowired
文件夹中新建一个Autowired.java程序。这里具体代码为
1 2 3 4 5 6 7
| @Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME) public @interface Autowired {
}
|
根据上述定义可以知道,Autowired 修饰成员变量(属性),并且在运行时生效。
那么为了实现该注解 ,可以使用以下方法:运行时利用反射获取所有标注了 Autowired 注解的成员变量,把它初始化成一个 Bean,然后注入属性。
因此,结合前面我们定义的 BeanPostProcessor
接口,我们来定义 Autowired 的处理类 AutowiredAnnotationBeanPostProcessor
,将其放在 annotation
文件夹中。
从下面代码可以看出,属性名字很关键,我们就是靠它来获取和创建的 Bean。有了 Bean 之后,我们通过反射设置属性值,完成依赖注入。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| package com.minis.beans.factory.annotation;
import com.minis.beans.BeansException; import com.minis.beans.factory.config.BeanPostProcessor; import com.minis.beans.factory.support.SimpleBeanFactory;
import java.lang.reflect.Field;
public class AutowiredAnnotationBeanPostProcessor implements BeanPostProcessor { private SimpleBeanFactory beanFactory;
@Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { Object result = bean;
Class<?> clazz = result.getClass(); Field[] fields = clazz.getDeclaredFields(); if(fields!=null){ for(Field field : fields){ boolean isAutowired = field.isAnnotationPresent(Autowired.class); if(isAutowired){ String fieldName = field.getName(); Object autowiredObj = this.getBeanFactory().getBean(fieldName); try { field.setAccessible(true); field.set(bean, autowiredObj); System.out.println("autowire " + fieldName + " for bean " + beanName); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } } } return null; }
@Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return null; } public SimpleBeanFactory getBeanFactory() { return beanFactory; }
public void setBeanFactory(SimpleBeanFactory beanFactory) { this.beanFactory = beanFactory; } }
|
新的BeanFactory
在此之前我们已经定义了 BeanFactory
接口,以及一个 SimpleBeanFactory
的实现类。现在我们又需要引入另外一个 BeanFactory ————AutowireCapableBeanFactory
,用于专为 Autowired 注入的 Bean 准备的。
基于代码复用、解耦的原则,我们可以对通用部分代码进行抽象,抽象出一个 AbstractBeanFactory
类,其中包括refresh()、getBean()、registerBeanDefinition() 等方法。因为这些方法提供了默认实现,确保这些方法即使不再被其他 BeanFactory
实现也能正常生效。
AbstractBeanFactory
的完整实现这里不再贴出,将其放在support文件夹中。
下面是其部分核心改动。
- 定义了抽象方法 applyBeanPostProcessorBeforeInitialization 与 applyBeanPostProcessorAfterInitialization,由名字可以看出,分别是在 Bean 处理类初始化之前和之后执行的方法。这两个方法交给具体的继承类去实现。
- 在 getBean() 方法中,在以前预留的位置,实现了对 Bean 初始化前、初始化和初始化后的处理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements BeanFactory,BeanDefinitionRegistry{ private Map<String,BeanDefinition> beanDefinitionMap=new ConcurrentHashMap<>(256); private List<String> beanDefinitionNames=new ArrayList<>(); private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
public AbstractBeanFactory() { }
public Object getBean(String beanName) throws BeansException{ Object singleton = this.getSingleton(beanName);
if (singleton == null) { singleton = this.earlySingletonObjects.get(beanName); if (singleton == null) { System.out.println("get bean null -------------- " + beanName); BeanDefinition bd = beanDefinitionMap.get(beanName); singleton=createBean(bd); this.registerBean(beanName, singleton);
applyBeanPostProcessorsBeforeInitialization(singleton, beanName);
if (bd.getInitMethodName() != null && !bd.getInitMethodName().equals("")) { invokeInitMethod(bd, singleton); }
applyBeanPostProcessorsAfterInitialization(singleton, beanName); }
} if (singleton == null) { throw new BeansException("bean is null."); } return singleton; }
...... abstract public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException;
abstract public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException;
}
|
由此,我们就可去实现AutowireCapableBeanFactory
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
|
public class AutowireCapableBeanFactory extends AbstractBeanFactory { private final List<AutowiredAnnotationBeanPostProcessor> beanPostProcessors = new ArrayList<AutowiredAnnotationBeanPostProcessor>();
public void addBeanPostProcessor(AutowiredAnnotationBeanPostProcessor beanPostProcessor) { this.beanPostProcessors.remove(beanPostProcessor); this.beanPostProcessors.add(beanPostProcessor); }
public int getBeanPostProcessorCount() { return this.beanPostProcessors.size(); }
public List<AutowiredAnnotationBeanPostProcessor> getBeanPostProcessors() { return this.beanPostProcessors; }
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean; for (AutowiredAnnotationBeanPostProcessor beanProcessor : getBeanPostProcessors()) { beanProcessor.setBeanFactory(this); result = beanProcessor.postProcessBeforeInitialization(result, beanName); if (result == null) { return result; } } return result; }
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean; for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { result = beanProcessor.postProcessAfterInitialization(result, beanName); if (result == null) { return result; } } return result; }
}
|
调整 ClassPathXmlApplicationContext
最后则是调整 ClassPathXmlApplicationContext,引入的成员变量由 SimpleBeanFactory 改为新建的 AutowireCapableBeanFactory,并在构造函数里增加上下文刷新逻辑。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
| public class ClassPathXmlApplicationContext implements BeanFactory,ApplicationEventPublisher{ AutowireCapableBeanFactory beanFactory; private final List<BeanFactoryPostProcessor> beanFactoryPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
public ClassPathXmlApplicationContext(String fileName){ this(fileName, true); }
public ClassPathXmlApplicationContext(String fileName, boolean isRefresh){ Resource res = new ClassPathXmlResource(fileName); AutowireCapableBeanFactory bf = new AutowireCapableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(bf); reader.loadBeanDefinitions(res);
this.beanFactory = bf;
if (isRefresh) { try { refresh(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (BeansException e) { e.printStackTrace(); } } }
@Override public Object getBean(String beanName) throws BeansException { return this.beanFactory.getBean(beanName); }
@Override public Boolean containsBean(String name) { return this.beanFactory.containsBean(name); }
public void registerBean(String beanName, Object obj) { this.beanFactory.registerBean(beanName, obj); }
@Override public void publishEvent(ApplicationEvent event) { }
@Override public boolean isSingleton(String name) { return false; }
@Override public boolean isPrototype(String name) { return false; }
@Override public Class<?> getType(String name) { return null; }
public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() { return this.beanFactoryPostProcessors; }
public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor) { this.beanFactoryPostProcessors.add(postProcessor); }
public void refresh() throws BeansException, IllegalStateException { registerBeanPostProcessors(this.beanFactory);
onRefresh(); }
private void registerBeanPostProcessors(AutowireCapableBeanFactory bf) { bf.addBeanPostProcessor(new AutowiredAnnotationBeanPostProcessor()); }
private void onRefresh() { this.beanFactory.refresh(); }
}
|
小结
最后,我们来回顾一下完整的过程。
启动 ClassPathXmlApplicationContext 容器,执行 refresh()。
在 refresh 执行过程中,调用 registerBeanPostProcessors(),往 BeanFactory 里注册 Bean 处理器,如 AutowiredAnnotationBeanPostProcessor。
执行 onRefresh(), 执行 AbstractBeanFactory 的 refresh() 方法。
AbstractBeanFactory 的 refresh() 获取所有 Bean 的定义,执行 getBean() 创建 Bean 实例。
getBean() 创建完 Bean 实例后,调用 Bean 处理器并初始化。
1 2 3
| applyBeanPostProcessorBeforeInitialization(singleton, beanName); invokeInitMethod(beanDefinition, singleton); applyBeanPostProcessorAfterInitialization(singleton, beanName);
|
applyBeanPostProcessorBeforeInitialization 由具体的 BeanFactory,如 AutowireCapableBeanFactory,来实现,,即对 BeanFactory 里已经注册好的所有 Bean 处理器调用相关方法。
1 2
| beanProcessor.postProcessBeforeInitialization(result, beanName); beanProcessor.postProcessAfterInitialization(result, beanName);
|
我们事先准备好的 AutowiredAnnotationBeanPostProcessor 方法里面会解释 Bean 中的 Autowired 注解。