文章目录
1.目录 2.SmartAnimal.java 接口(JDK代理必须有接口) 3.SmartDog.java 4.SmartAnimalAspect.java 5.SunSpringApplicationContext.java 1.在Bean的后置处理器之后使用动态代理 2.完整代码
6.测试 1.AppMain.java 调用被代理的类的方法 2.结果
7.Spring底层机制总结 1.扫描包,存储Bean定义信息,初始化单例池,依赖注入 2.后置处理器的Before方法对Bean进行处理 3.实现InitializingBean接口或者有@PostConstruct注解的初始化方法被调用 4.后置处理器的After方法对Bean进行处理 5.如果发现某个类被AOP了,则在后置处理器之后就会返回代理对象,当目标对象使用代理对象调用方法时,就可以得到目标对象和调用的方法的信息
1.目录
2.SmartAnimal.java 接口(JDK代理必须有接口)
package com. sunxiansheng. sunspring. compent ;
public interface SmartAnimal {
public float getSum ( float a, float b) ;
public float getSub ( float a, float b) ;
}
3.SmartDog.java
package com. sunxiansheng. sunspring. compent ;
import com. sunxiansheng. sunspring. annotation. Component ;
import org. slf4j. Logger ;
import org. slf4j. LoggerFactory ;
@Component
public class SmartDog implements SmartAnimal {
private static final Logger log = LoggerFactory . getLogger ( SmartDog . class ) ;
@Override
public float getSum ( float a, float b) {
log. info ( "SmartDog...getSum...res=" + ( a + b) ) ;
return a + b;
}
@Override
public float getSub ( float a, float b) {
log. info ( "SmartDog...getSub...res=" + ( a - b) ) ;
return a - b;
}
}
4.SmartAnimalAspect.java
package com. sunxiansheng. sunspring. compent ;
import org. slf4j. Logger ;
import org. slf4j. LoggerFactory ;
public class SmartAnimalAspect {
private static final Logger log = LoggerFactory . getLogger ( SmartAnimalAspect . class ) ;
public static void showBeginLog ( ) {
log. info ( "AOP:前置通知-方法执行开始" ) ;
}
public static void showEndLog ( ) {
log. info ( "AOP:后置通知-方法执行结束" ) ;
}
}
5.SunSpringApplicationContext.java
1.在Bean的后置处理器之后使用动态代理
2.完整代码
package com. sunxiansheng. sunspring. ioc ;
import com. sunxiansheng. sunspring. annotation. * ;
import com. sunxiansheng. sunspring. annotation. myenum. MyScope ;
import com. sunxiansheng. sunspring. compent. SmartAnimalAspect ;
import com. sunxiansheng. sunspring. processor. BeanPostProcessor ;
import com. sunxiansheng. sunspring. processor. InitializingBean ;
import org. slf4j. Logger ;
import org. slf4j. LoggerFactory ;
import java. io. File ;
import java. lang. reflect. Field ;
import java. lang. reflect. InvocationTargetException ;
import java. lang. reflect. Proxy ;
import java. net. URL ;
import java. util. ArrayList ;
import java. util. List ;
import java. util. concurrent. ConcurrentHashMap ;
public class SunSpringApplicationContext {
private static final Logger log = LoggerFactory . getLogger ( SunSpringApplicationContext . class ) ;
private ConcurrentHashMap < String , BeanDefintion > beanDefintionMap = new ConcurrentHashMap < > ( ) ;
private ConcurrentHashMap < String , Object > singletonObjects = new ConcurrentHashMap < > ( ) ;
private List < BeanPostProcessor > beanPostProcessorList = new ArrayList < > ( ) ;
public SunSpringApplicationContext ( Class < ? > configClass) throws ClassNotFoundException , InstantiationException , IllegalAccessException {
beanDefinitionByScan ( configClass) ;
initSingletonObjects ( ) ;
}
private void populateBeans ( Object bean) {
Class < ? > clazz = bean. getClass ( ) ;
Field [ ] fields = clazz. getDeclaredFields ( ) ;
for ( Field field : fields) {
if ( field. isAnnotationPresent ( Resource . class ) ) {
String fieldName = field. getName ( ) ;
Object beanObject = null ;
BeanDefintion beanDefintion = beanDefintionMap. get ( fieldName) ;
try {
beanObject = getBean ( fieldName) ;
} catch ( Exception e) {
throw new RuntimeException ( e) ;
}
field. setAccessible ( true ) ;
try {
field. set ( bean, beanObject) ;
log. info ( "依赖注入成功:{} => {}.{}" , beanObject. getClass ( ) , clazz, fieldName) ;
} catch ( IllegalAccessException e) {
e. printStackTrace ( ) ;
}
}
}
}
private void initSingletonObjects ( ) {
beanDefintionMap. forEach ( ( beanName, beanDefintion) -> {
try {
Object bean = createBean ( beanDefintion) ;
if ( bean != null ) {
singletonObjects. put ( beanName, bean) ;
}
} catch ( Exception e) {
e. printStackTrace ( ) ;
}
} ) ;
log. info ( "根据bean定义信息初始化单例池:{}" , singletonObjects) ;
}
public Object getBean ( String name) throws Exception {
BeanDefintion beanDefintion = beanDefintionMap. get ( name) ;
if ( beanDefintion == null ) {
throw new NullPointerException ( "在bean定义中没有找到bean对象" ) ;
}
MyScope scope = beanDefintion. getScope ( ) ;
Object bean = null ;
if ( scope == MyScope . SINGLETON ) {
bean = singletonObjects. get ( name) ;
} else {
bean = createProtoTypeBean ( beanDefintion) ;
}
populateBeans ( bean) ;
Object current = bean;
for ( BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
Object bean1 = beanPostProcessor. postProcessBeforeInitialization ( bean, name) ;
if ( bean1 != null ) {
current = bean1;
}
}
init ( current) ;
for ( BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
bean = beanPostProcessor. postProcessAfterInitialization ( current, name) ;
if ( bean == null ) {
bean = current;
}
}
if ( name. equals ( "smartDog" ) ) {
final Object proxyObject = current;
bean = Proxy . newProxyInstance ( current. getClass ( ) . getClassLoader ( ) , current. getClass ( ) . getInterfaces ( ) , ( proxy, method, args) -> {
SmartAnimalAspect . showBeginLog ( ) ;
Object invoke = method. invoke ( proxyObject, args) ;
SmartAnimalAspect . showEndLog ( ) ;
return invoke;
} ) ;
log. info ( "SmartDog返回代理对象:{}" , bean. getClass ( ) ) ;
return bean;
}
log. info ( "getBean:{}" , bean. getClass ( ) ) ;
return bean;
}
public void init ( Object bean) {
if ( bean instanceof InitializingBean ) {
( ( InitializingBean ) bean) . afterPropertiesSet ( ) ;
}
}
private Object createBean ( BeanDefintion beanDefintion) throws Exception {
Class < ? > clazz = beanDefintion. getClazz ( ) ;
if ( beanDefintion. getScope ( ) == MyScope . PROTOTYPE ) {
return null ;
}
Object bean = clazz. getDeclaredConstructor ( ) . newInstance ( ) ;
return bean;
}
private static Object createProtoTypeBean ( BeanDefintion beanDefintion) throws InstantiationException , IllegalAccessException , InvocationTargetException , NoSuchMethodException {
Class < ? > clazz = beanDefintion. getClazz ( ) ;
Object bean = clazz. getDeclaredConstructor ( ) . newInstance ( ) ;
return bean;
}
private void beanDefinitionByScan ( Class < ? > configClass) {
ComponentScan componentScan = configClass. getDeclaredAnnotation ( ComponentScan . class ) ;
String path = componentScan. packagePath ( ) ;
log. info ( "扫描的包路径:{}" , path) ;
ClassLoader classLoader = SunSpringApplicationContext . class . getClassLoader ( ) ;
path = path. replace ( "." , "/" ) ;
URL resource = classLoader. getResource ( path) ;
File file = new File ( resource. getFile ( ) ) ;
if ( file. isDirectory ( ) ) {
File [ ] files = file. listFiles ( ) ;
for ( File f : files) {
String absolutePath = f. getAbsolutePath ( ) ;
if ( absolutePath. endsWith ( ".class" ) ) {
String className = extractClassName ( absolutePath) ;
String fullPath = path. replace ( "/" , "." ) + "." + className;
Class < ? > aClass = null ;
try {
aClass = classLoader. loadClass ( fullPath) ;
} catch ( ClassNotFoundException e) {
throw new RuntimeException ( e) ;
}
if ( aClass. isAnnotationPresent ( Component . class ) ) {
log. info ( "扫描到Spring Bean:{}" , aClass) ;
if ( BeanPostProcessor . class . isAssignableFrom ( aClass) ) {
Object o = null ;
try {
o = aClass. getDeclaredConstructor ( ) . newInstance ( ) ;
} catch ( Exception e) {
log. info ( "BeanPostProcessor实例化失败:{}" , e) ;
}
if ( o instanceof BeanPostProcessor ) {
beanPostProcessorList. add ( ( BeanPostProcessor ) o) ;
}
log. info ( "BeanPostProcessor实例化成功:{}" , o) ;
continue ;
}
BeanDefintion beanDefintion = new BeanDefintion ( ) ;
if ( aClass. isAnnotationPresent ( Scope . class ) ) {
Scope scope = aClass. getDeclaredAnnotation ( Scope . class ) ;
MyScope value = scope. value ( ) ;
beanDefintion. setScope ( value) ;
} else {
beanDefintion. setScope ( MyScope . SINGLETON ) ;
}
beanDefintion. setClazz ( aClass) ;
Component component = aClass. getDeclaredAnnotation ( Component . class ) ;
String beanName = component. value ( ) ;
if ( "" . equals ( beanName) ) {
beanName = className. substring ( 0 , 1 ) . toLowerCase ( ) + className. substring ( 1 ) ;
}
beanDefintionMap. put ( beanName, beanDefintion) ;
} else {
log. info ( "这不是一个Spring Bean={}" , aClass) ;
}
}
}
}
log. info ( "将bean定义信息放到beanDefintionMap:{}" , beanDefintionMap) ;
}
private String extractClassName ( String filePath) {
int lastSlashIndex = filePath. lastIndexOf ( '/' ) ;
int lastDotIndex = filePath. lastIndexOf ( '.' ) ;
return filePath. substring ( lastSlashIndex + 1 , lastDotIndex) ;
}
}
6.测试
1.AppMain.java 调用被代理的类的方法
2.结果
7.Spring底层机制总结
1.扫描包,存储Bean定义信息,初始化单例池,依赖注入
2.后置处理器的Before方法对Bean进行处理
3.实现InitializingBean接口或者有@PostConstruct注解的初始化方法被调用
4.后置处理器的After方法对Bean进行处理
5.如果发现某个类被AOP了,则在后置处理器之后就会返回代理对象,当目标对象使用代理对象调用方法时,就可以得到目标对象和调用的方法的信息