- 1. Spring注解开发用法
- 2. Spring Bean的生命周期
- 3. 手写 Spring IOC 容器
- 1. 自定义 @Component 注解
- 2. 自定义 @Scope 注解
- 3. 自定义 @ComponentScan 注解
- 4. 自定义 @Autowired 注解
- 5. 自定义 BeanDefinition
- 6. 自定义 InitializingBean
- 7. 自定义 BeanPostProcessor
- 8. 自定义 AnnotationConfigApplicationContext
- 9. 测试
- 4. 回顾注解和反射用法 Demo
- 5. 回顾ClassLoader用法 Demo
① OrderDao :
package com.chahua.spring.source.dao;
import org.springframework.stereotype.Repository;
@Repository
public class OrderDao {
public void hello(){
System.out.println("order dao hello....");
}
}
② 在OrderService中注入OrderDao对象:
package com.chahua.spring.source.service;
import com.chahua.spring.source.dao.OrderDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class OrderService {
@Autowired
private OrderDao orderDao;
public void hello(){
System.out.println("orderService hello....");
orderDao.hello();
}
}
③ 定义配置类,扫描注解所在的包:
package com.chahua.spring.source.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
// @Configuration 指定此类为Spring配置类,作为配置类,替代XML配置文件
// @ComponentScan主要就是定义扫描的路径从中找出标识了需要装配的类自动装配到spring的bean容器中
// @ComponentScan注解默认就会装配标识了@Controller,@Service,@Repository,@Component注解的类到spring容器中
@Configuration
@ComponentScan("com.chahua.spring.source")
public class AppConfig {
}
④ 测试:
public class Bootstrap {
public static void main(String[] args) {
AnnotationConfigApplicationContext context
= new AnnotationConfigApplicationContext(AppConfig.class);
OrderService orderService = (OrderService)context.getBean("orderService");
orderService.hello();
}
}
2. Spring Bean的生命周期Task :chahua-spring:Bootstrap.main()
orderService hello…
order dao hello…
@Service
public class OrderService implements InitializingBean {
// 构造器
public OrderService(){
System.out.println("OrderService constructor.....");
}
@Autowired
private OrderDao orderDao;
public void hello(){
System.out.println("orderService hello....");
orderDao.hello();
}
// 初始化
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("OrderService initializing.....");
}
}
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
// Bean的初始化前置操作
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof OrderService){
System.out.println("OrderService postProcessBeforeInitialization.....");
}
return null;
}
// Bean的初始化后置操作
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof OrderService){
System.out.println("OrderService postProcessAfterInitialization.....");
}
return null;
}
}
public class Bootstrap {
public static void main(String[] args) {
AnnotationConfigApplicationContext context
= new AnnotationConfigApplicationContext(AppConfig.class);
OrderService orderService = (OrderService)context.getBean("orderService");
orderService.hello();
}
}
3. 手写 Spring IOC 容器 1. 自定义 @Component 注解Task :chahua-spring:Bootstrap.main()
OrderService constructor…
OrderService postProcessBeforeInitialization…
OrderService initializing…
OrderService postProcessAfterInitialization…
orderService hello…
order dao hello…
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {
String value() default "";
}
2. 自定义 @Scope 注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Scope {
String value() default "singleton";
}
3. 自定义 @ComponentScan 注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ComponentScan {
String value() default "";
}
4. 自定义 @Autowired 注解
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
boolean required() default true;
}
5. 自定义 BeanDefinition
@Data
public class BeanDefinition {
private String beanName;
Class> classType;
String scope;
}
6. 自定义 InitializingBean
public interface InitializingBean {
void afterPropertiesSet() throws Exception;
}
7. 自定义 BeanPostProcessor
public interface BeanPostProcessor {
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
public class BeansException extends RuntimeException{
public BeansException(String msg) {
super(msg);
}
public BeansException(String msg, Throwable cause) {
super(msg, cause);
}
}
8. 自定义 AnnotationConfigApplicationContext
public class AnnotationConfigApplicationContext {
private final Class> configClass;
private Map beanDefinitionMap = new ConcurrentHashMap();
private Map singletonObjects = new ConcurrentHashMap<>();
private List beanPostProcessors = new ArrayList<>();
public AnnotationConfigApplicationContext(Class> configClass){
this.configClass = configClass;
// 1. 扫描所有的包路径,解析所有文件信息,做判断
// 2. 注册,如果说是符合条件的bean(Component注解的类),将相关的bean信息转换为BeanDefinition
doScan();
// 3. 实例化,单例对象,非懒加载的Bean
initializeNotLazyBean();
}
private void doScan() {
if(!configClass.isAnnotationPresent(ComponentScan.class)){
return;
}
ComponentScan annotation = configClass.getAnnotation(ComponentScan.class);
// com.chahua.biz
String packageName = annotation.value();
// filePath: com/chahua/biz
String filePath = packageName.replaceAll("\.", "/");
ClassLoader classLoader = this.getClass().getClassLoader();
// file:/D:/source_study/spring_source/spring-ioc-1/target/classes/com/chahua/biz
URL resource = classLoader.getResource(filePath);
// /D:/source_study/spring_source/spring-ioc-1/target/classes/com/chahua/biz
filePath = resource.getFile();
File file = new File(filePath);
if(file.isDirectory()){
File[] files = file.listFiles();
for (File file1 : files) {
// 获取类路径
// com.chahua.biz.AppConfig
String className = packageName+"."+file1.getName().replaceAll(".class","");
// 获取到了类的全路径,从而可以通过反射获取类上的注解
try {
Class> aClass = Class.forName(className);
if(aClass.isAnnotationPresent(Component.class)){
String beanName;
Component component = aClass.getAnnotation(Component.class);
if("".equals(component.value())){
// 给一个默认值
beanName = Introspector.decapitalize(aClass.getSimpleName());
}else{
beanName = component.value();
}
String scope = ScopeType.SINGLETON;
if(aClass.isAnnotationPresent(Scope.class)){
scope = aClass.getAnnotation(Scope.class).value();
// 判断是不是scope类型
}
BeanDefinition definition = new BeanDefinition();
definition.setClassType(aClass);
definition.setBeanName(beanName);
definition.setScope(scope);
beanDefinitionMap.put(beanName,definition);
// 判断这个aClass对象是否是BeanPostProcessor类的衍生子类
if(BeanPostProcessor.class.isAssignableFrom(aClass)){
BeanPostProcessor beanPostProcessor = (BeanPostProcessor)getBean(beanName);
beanPostProcessors.add(beanPostProcessor);
}
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}
}
private void initializeNotLazyBean() {
Set> entries = beanDefinitionMap.entrySet();
for (Map.Entry entry : entries) {
BeanDefinition beanDefinition = entry.getValue();
String scope = beanDefinition.getScope();
if(ScopeType.SINGLETON.equals(scope)){
craeteBean(beanDefinition);
}
}
}
private Object craeteBean(BeanDefinition beanDefinition) {
String beanName = beanDefinition.getBeanName();
if(singletonObjects.containsKey(beanName)){
return singletonObjects.get(beanName);
}
// 创建Bean
Object bean = doCreateBean(beanDefinition);
singletonObjects.put(beanName,bean);
return bean;
}
private Object doCreateBean(BeanDefinition beanDefinition) {
Object exposedObject = null;
Class> classType = beanDefinition.getClassType();
try {
// 实例化
Object instance = classType.getConstructor().newInstance();
// 属性填充
populateBean(instance,beanDefinition);
// 对象初始化
exposedObject = initializing(instance, beanDefinition);
} catch (Exception e) {
throw new BeansException(beanDefinition.getBeanName()+":创建异常");
}
return exposedObject;
}
private Object initializing(Object instance, BeanDefinition beanDefinition) throws Exception {
// 初始化前置操作
Object rs = postProcessBeforeInitialization(instance,beanDefinition.getBeanName());
if(rs!=null){
return rs;
}
// 实际初始化过程
if(instance instanceof InitializingBean){
((InitializingBean) instance).afterPropertiesSet();
}
// 初始化后置操作
rs = postProcessAfterInitialization(instance,beanDefinition.getBeanName());
if(rs!=null){
return rs;
}
return instance;
}
private Object postProcessBeforeInitialization(Object instance, String beanName) {
if(instance instanceof BeanPostProcessor){
return instance;
}
for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
Object o = beanPostProcessor.postProcessBeforeInitialization(instance, beanName);
if(o!=null){
return o;
}
}
return null;
}
private Object postProcessAfterInitialization(Object instance, String beanName) {
if(instance instanceof BeanPostProcessor){
return instance;
}
for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
Object o = beanPostProcessor.postProcessAfterInitialization(instance, beanName);
if(o!=null){
return o;
}
}
return null;
}
private void populateBean(Object instance, BeanDefinition beanDefinition) {
Class> classType = beanDefinition.getClassType();
// 获取类中所有可访问的字段(包括私有)
Field[] declaredFields = classType.getDeclaredFields();
try{
for (Field declaredField : declaredFields) {
// 判断字段上是否有@Autowired注解
if(declaredField.isAnnotationPresent(Autowired.class)){
// 获取属性的类型
String simpleName = declaredField.getType().getSimpleName();
// 将simpleName的首字符从大写转换成小写
String fieldBeanName = Introspector.decapitalize(simpleName);
declaredField.setAccessible(true);
declaredField.set(instance,getBean(fieldBeanName));
}
}
}catch (Exception e){
e.printStackTrace();
throw new BeansException(beanDefinition.getBeanName()+":创建异常");
}
}
public Object getBean(String beanName){
if(!beanDefinitionMap.containsKey(beanName)){
throw new BeansException("找不到这样的Bean定义....");
}
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
// 如果是单例
if(ScopeType.SINGLETON.equals(beanDefinition.getScope())){
return craeteBean(beanDefinition);
}else {
return doCreateBean(beanDefinition);
}
}
}
9. 测试
import com.chahua.spring.annotation.Component;
@Component
public class Orderdao {
public void hello(){
System.out.println("OrderDao hello .... ");
}
}
import com.chahua.spring.annotation.Autowired;
import com.chahua.spring.annotation.Component;
import com.chahua.spring.annotation.Scope;
import com.chahua.spring.bean.InitializingBean;
@Component
@Scope("prototype")
public class OrderService implements InitializingBean {
@Autowired
private OrderDao orderDao;
public void hello(){
System.out.println("OrderService hello ... ");
orderDao.hello();
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("OrderService afterPropertiesSet.....");
}
}
import com.chahua.spring.annotation.Component;
import com.chahua.spring.annotation.ComponentScan;
@Component
@ComponentScan("com.chahua.biz")
public class AppConfig {
}
import com.chahua.spring.annotation.Component;
import com.chahua.spring.bean.BeanPostProcessor;
import com.chahua.spring.exception.BeansException;
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
// Bean的初始化前置操作
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof OrderService){
System.out.println("OrderService postProcessBeforeInitialization.....");
}
return null;
}
// Bean的初始化后置操作
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof OrderService){
System.out.println("OrderService postProcessAfterInitialization.....");
}
return null;
}
}
import com.chahua.biz.config.AppConfig;
import com.chahua.biz.service.OrderService;
import com.chahua.spring.context.AnnotationConfigApplicationContext;
public class Bootstrape {
public static void main(String[] args) {
AnnotationConfigApplicationContext context
= new AnnotationConfigApplicationContext(AppConfig.class);
OrderService orderService = (OrderService) context.getBean("orderService");
orderService.hello();
}
}
测试结果:
4. 回顾注解和反射用法 DemoOrderService postProcessBeforeInitialization…
OrderService afterPropertiesSet…
OrderService postProcessAfterInitialization…
OrderService hello …
OrderDao hello …
import org.springframework.stereotype.Component;
@ComponentScan("com.example.fileupload.test")
public class AppConfig {
}
public class Main {
public static void main(String[] args) throws Exception {
// 获取Class类对象
Class> clazz = Class.forName("com.example.fileupload.test.AppConfig");
// 1. 判断该类上是否存在指定类型的注解,如果存在则返回true,否则返回false。
boolean annotationPresent = clazz.isAnnotationPresent(ComponentScan.class);
// true
System.out.println(annotationPresent);
// 2.获取类上指定类型的注解
ComponentScan annotation = clazz.getAnnotation(ComponentScan.class);
// 3.获取注解的属性值
String[] values = annotation.value();
for (String value : values) {
// com.example.fileupload.test
System.out.println(value);
}
}
}
5. 回顾ClassLoader用法 Demo
测试demo目录 :
public class AppConfig {
}
public class Main {
public static void main(String[] args) throws Exception {
ClassLoader classLoader = AppConfig.class.getClassLoader();
URL resource = classLoader.getResource("com/example/fileupload/test");
String filePath = resource.getFile();
// file:/D:/code/fileupload-test/target/classes/com/example/fileupload/test
System.out.println(resource);
// /D:/code/fileupload-test/target/classes/com/example/fileupload/test
System.out.println(filePath);
File file = new File(filePath);
if(file.isDirectory()){
File[] files = file.listFiles();
for (File file1 :files){
System.out.println(file1);
System.out.println(file1.getName());
}
}
}
}
输出:



