SSM 소스 코드 분석의 Spring 08 - 핸드폰 SpringV 2.0
이 소절, 우 리 는 spring 소스 코드 에 따라 IOC 와 AOP 소스 코드 를 한층 더 봉인 합 니 다 ~
핸드폰 SpringV 2.0
모든 것 은 Application Context 컨 텍스트 에서 시작 합 니 다.
spring 의 Application Context 의 가장 핵심 적 인 방법 은 refresh 입 니 다. 이것 은 우리 가 전에 말 했 기 때문에 제 가 먼저 refresh 방법 을 미리 남 겨 두 었 습 니 다.
public class GPApplicationContext{
public void refresh(){}
}
그리고 BeanFactory 를 실현 시 키 도록 하 겠 습 니 다.
public interface GPBeanFactory {
/**
* beanName IOC Bean
* @param beanName
* @return
*/
Object getBean(String beanName);
}
획득:
public class GPApplicationContext implements GPBeanFactory {
private String [] configLocations;
private GPBeanDefinitionReader reader;
//
private Map<String,Object> beanCacheMap = new HashMap<String, Object>();
//
private Map<String,GPBeanWrapper> beanWrapperMap = new ConcurrentHashMap<String, GPBeanWrapper>();
public GPApplicationContext(String ... configLocations){
this.configLocations = configLocations;
refresh();
}
// , , BeanDefinition
// ,
//Spring , , BeanWrapper
// :
//1、 OOP
//2、 , ( AOP )
@Override
public Object getBean(String beanName) {
GPBeanDefinition beanDefinition = this.beanDefinitionMap.get(beanName);
String className = beanDefinition.getBeanClassName();
try{
//
GPBeanPostProcessor beanPostProcessor = new GPBeanPostProcessor();
Object instance = instantionBean(beanDefinition);
if(null == instance){ return null;}
//
beanPostProcessor.postProcessBeforeInitialization(instance,beanName);
GPBeanWrapper beanWrapper = new GPBeanWrapper(instance);
beanWrapper.setAopConfig(instantionAopConfig(beanDefinition));
beanWrapper.setPostProcessor(beanPostProcessor);
this.beanWrapperMap.put(beanName,beanWrapper);
//
beanPostProcessor.postProcessAfterInitialization(instance,beanName);
// populateBean(beanName,instance);
// ,
return this.beanWrapperMap.get(beanName).getWrappedInstance();
}catch (Exception e){
e.printStackTrace();
}
return null;
}
private GPAopConfig instantionAopConfig(GPBeanDefinition beanDefinition) throws Exception{
GPAopConfig config = new GPAopConfig();
String expression = reader.getConfig().getProperty("pointCut");
String[] before = reader.getConfig().getProperty("aspectBefore").split("\\s");
String[] after = reader.getConfig().getProperty("aspectAfter").split("\\s");
String className = beanDefinition.getBeanClassName();
Class<?> clazz = Class.forName(className);
Pattern pattern = Pattern.compile(expression);
Class aspectClass = Class.forName(before[0]);
//
for (Method m : clazz.getMethods()){
//public .* com\.gupaoedu\.vip\.spring\.demo\.service\..*Service\..*\(.*\)
//public java.lang.String com.gupaoedu.vip.spring.demo.service.impl.ModifyService.add(java.lang.String,java.lang.String)
Matcher matcher = pattern.matcher(m.toString());
if(matcher.matches()){
// , AOP
config.put(m,aspectClass.newInstance(),new Method[]{aspectClass.getMethod(before[1]),aspectClass.getMethod(after[1])});
}
}
return config;
}
// BeanDefinition, Bean
private Object instantionBean(GPBeanDefinition beanDefinition){
Object instance = null;
String className = beanDefinition.getBeanClassName();
try{
// Class
if(this.beanCacheMap.containsKey(className)){
instance = this.beanCacheMap.get(className);
}else{
Class<?> clazz = Class.forName(className);
instance = clazz.newInstance();
this.beanCacheMap.put(className,instance);
}
return instance;
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}
BeanDefinitionReader 는 설정 파일 을 찾 고 읽 고 해석 합 니 다.
public class GPBeanDefinitionReader {
private Properties config = new Properties();
private List<String> registyBeanClasses = new ArrayList<String>();
// , key
private final String SCAN_PACKAGE = "scanPackage";
public GPBeanDefinitionReader(String... locations){
// Spring Reader
InputStream is = this.getClass().getClassLoader().getResourceAsStream(locations[0].replace("classpath:",""));
try {
config.load(is);
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(null != is){is.close();}
}catch (Exception e){
e.printStackTrace();
}
}
doScanner(config.getProperty(SCAN_PACKAGE));
}
public List<String> loadBeanDefinitions(){
return this.registyBeanClasses;
}
// className, BeanDefinition,
//
public GPBeanDefinition registerBean(String className){
if(this.registyBeanClasses.contains(className)){
GPBeanDefinition beanDefinition = new GPBeanDefinition();
beanDefinition.setBeanClassName(className);
beanDefinition.setFactoryBeanName(lowerFirstCase(className.substring(className.lastIndexOf(".") + 1)));
return beanDefinition;
}
return null;
}
// class, List
private void doScanner(String packageName) {
URL url = this.getClass().getClassLoader().getResource("/" + packageName.replaceAll("\\.","/"));
File classDir = new File(url.getFile());
for (File file : classDir.listFiles()){
if(file.isDirectory()){
doScanner(packageName + "." +file.getName());
}else {
registyBeanClasses.add(packageName + "." + file.getName().replace(".class",""));
}
}
}
public Properties getConfig(){
return this.config;
}
private String lowerFirstCase(String str){
char [] chars = str.toCharArray();
chars[0] += 32;
return String.valueOf(chars);
}
}
BeanDefinition 은 설정 파일 의 정 보 를 저장 하 는 데 사 용 됩 니 다.
BeanDefinition 은 메모리 에 저 장 된 설정 에 해당 합 니 다.
public class GPBeanDefinition {
private String beanClassName;
private boolean lazyInit = false;
private String factoryBeanName;
public String getBeanClassName() {
return beanClassName;
}
public void setBeanClassName(String beanClassName) {
this.beanClassName = beanClassName;
}
public boolean isLazyInit() {
return lazyInit;
}
public void setLazyInit(boolean lazyInit) {
this.lazyInit = lazyInit;
}
public String getFactoryBeanName() {
return factoryBeanName;
}
public void setFactoryBeanName(String factoryBeanName) {
this.factoryBeanName = factoryBeanName;
}
}
BeanWrapper
public class GPBeanWrapper extends GPFactoryBean {
private GPAopProxy aopProxy = new GPAopProxy();
public GPBeanPostProcessor getPostProcessor() {
return postProcessor;
}
public void setPostProcessor(GPBeanPostProcessor postProcessor) {
this.postProcessor = postProcessor;
}
//
//1、 ,
private GPBeanPostProcessor postProcessor;
private Object wrapperInstance;
// new , ,
private Object originalInstance;
public GPBeanWrapper(Object instance){
// ,
this.wrapperInstance = aopProxy.getProxy(instance);
this.originalInstance = instance;
}
public Object getWrappedInstance(){
return this.wrapperInstance;
}
// Class
// $Proxy0
public Class<?> getWrappedClass(){
return this.wrapperInstance.getClass();
}
public void setAopConfig(GPAopConfig config){
aopProxy.setConfig(config);
}
public Object getOriginalInstance() {
return originalInstance;
}
}
BeanPost Processor 는 사건 감청 으로 사용 합 니 다.
public class GPBeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName){
return bean;
}
}
refresh 방법 은 포 지 셔 닝, 로드, 등록 기능 을 실현 합 니 다.
applicationContext 컨 텍스트 라 는 핵심 클래스 로 돌아 가 refresh 방법 을 실현 합 니 다.
public void refresh(){
//
this.reader = new GPBeanDefinitionReader(configLocations);
//
List<String> beanDefinitions = reader.loadBeanDefinitions();
//
doRegisty(beanDefinitions);
// (lazy-init = false),
// getBean
doAutowrited();
// MyAction myAction = (MyAction)this.getBean("myAction");
// myAction.query(null,null," Tom ");
}
그리고 등록 실현:
// BeanDefinitions beanDefinitionMap
private void doRegisty(List<String> beanDefinitions) {
//beanName :
//1、
//2、
//3、
try {
for (String className : beanDefinitions) {
Class<?> beanClass = Class.forName(className);
// ,
//
if(beanClass.isInterface()){ continue; }
GPBeanDefinition beanDefinition = reader.registerBean(className);
if(beanDefinition != null){
this.beanDefinitionMap.put(beanDefinition.getFactoryBeanName(),beanDefinition);
}
Class<?>[] interfaces = beanClass.getInterfaces();
for (Class<?> i: interfaces) {
// ,
// ? Spring ,
// ,
this.beanDefinitionMap.put(i.getName(),beanDefinition);
}
// ,
}
}catch (Exception e){
e.printStackTrace();
}
}
자동 주입 실현:
//
private void doAutowrited() {
for(Map.Entry<String,GPBeanDefinition> beanDefinitionEntry : this.beanDefinitionMap.entrySet()){
String beanName = beanDefinitionEntry.getKey();
if(!beanDefinitionEntry.getValue().isLazyInit()){
Object obj = getBean(beanName);
// System.out.println(obj.getClass());
}
}
for(Map.Entry<String,GPBeanWrapper> beanWrapperEntry : this.beanWrapperMap.entrySet()){
populateBean(beanWrapperEntry.getKey(),beanWrapperEntry.getValue().getOriginalInstance());
}
// System.out.println("===================");
}
public void populateBean(String beanName,Object instance){
Class clazz = instance.getClass();
//
if(!(clazz.isAnnotationPresent(GPController.class) ||
clazz.isAnnotationPresent(GPService.class))){
return;
}
Field [] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (!field.isAnnotationPresent(GPAutowired.class)){ continue; }
GPAutowired autowired = field.getAnnotation(GPAutowired.class);
String autowiredBeanName = autowired.value().trim();
if("".equals(autowiredBeanName)){
autowiredBeanName = field.getType().getName();
}
field.setAccessible(true);
try {
//System.out.println("=======================" +instance +"," + autowiredBeanName + "," + this.beanWrapperMap.get(autowiredBeanName));
field.set(instance,this.beanWrapperMap.get(autowiredBeanName).getWrappedInstance());
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
후기
springV 2.0 github 주소
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Spring Tool Suite (STS) 설치, 일본어 및 Gradle 플러그인 추가 단계Spring 애플리케이션 개발을 위한 통합 개발 환경으로 Spring Tool Suite(STS)를 설치하는 절차를 설명합니다. 필요에 따라 일본어화와 Gradle 플러그인을 추가하는 절차도 이용하십시오. 설치 대상...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.