文章目录
阶段4—实现BeanPostProcessor机制 1.文件目录 2.初始化方法实现 1.编写初始化接口InitializingBean.java 2.MonsterService.java实现初始化接口 3.容器中的createBean方法增加初始化逻辑,判断对象类型是否是InitializingBean的子类型,如果是,则转换成初始化接口类型执行初始化方法
3.后置处理器实现 1.编写后置处理器接口BeanPostProcessor.java 2.在组件文件夹下编写后置处理器实现类SunBeanPostProcessor.java会被容器扫描 3.容器类完整代码SunSpringApplicationContext.java 4.结果展示
4.该阶段完成的任务
阶段5—实现AOP机制&Spring底层机制总结 1.实现AOP机制 1.原理分析 2.代码实现 1.文件目录 2.编写接口SmartAnimalable.java 2.编写实现类SmartDog.java 3.编写切面类SmartAnimalAspect.java 4.修改SunBeanPostProcessor.java对SmartDog的getSum方法进行动态代理 5.启动类 6.结果展示
3.该阶段完成的任务
2.Spring底层机制总结 1.bean的生命周期 2.Spring容器的执行流程 3.动态代理和AOP的区别 4.关于后置处理器 + 动态代理的理解 5.AOP的使用方式
阶段4—实现BeanPostProcessor机制
1.文件目录
2.初始化方法实现
1.编写初始化接口InitializingBean.java
package com. sun. spring. processor ;
public interface InitializingBean {
void afterPropertiesSet ( ) throws Exception ;
}
2.MonsterService.java实现初始化接口
package com. sun. spring. component ;
import com. sun. spring. annotation. Autowired ;
import com. sun. spring. annotation. Component ;
import com. sun. spring. annotation. Scope ;
import com. sun. spring. processor. InitializingBean ;
@Scope ( value = "prototype" )
@Component ( value = "monsterService" )
public class MonsterService implements InitializingBean {
@Autowired
private MonsterDao monsterDao;
public void m1 ( ) {
monsterDao. hi ( ) ;
}
@Override
public void afterPropertiesSet ( ) throws Exception {
System . out. println ( "MonsterService 的初始化方法被调用!" ) ;
}
}
3.容器中的createBean方法增加初始化逻辑,判断对象类型是否是InitializingBean的子类型,如果是,则转换成初始化接口类型执行初始化方法
3.后置处理器实现
1.编写后置处理器接口BeanPostProcessor.java
package com. sun. spring. processor ;
public interface BeanPostProcessor {
default Object postProcessBeforeInitialization ( Object bean, String beanName) {
return bean;
}
default Object postProcessAfterInitialization ( Object bean, String beanName) {
return bean;
}
}
2.在组件文件夹下编写后置处理器实现类SunBeanPostProcessor.java会被容器扫描
package com. sun. spring. component ;
import com. sun. spring. annotation. Component ;
import com. sun. spring. processor. BeanPostProcessor ;
@Component
public class SunBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization ( Object bean, String beanName) {
System . out. println ( "\n后置处理器postProcessBeforeInitialization被调用 bean类型=" + bean. getClass ( ) + "bean名字=" + beanName) ;
if ( bean instanceof Car ) {
System . out. println ( "后置处理器发现这个类型是Car类型" ) ;
}
return bean;
}
@Override
public Object postProcessAfterInitialization ( Object bean, String beanName) {
System . out. println ( "后置处理器postProcessAfterInitialization被调用 bean类型=" + bean. getClass ( ) + "bean名字=" + beanName) ;
return bean;
}
}
3.容器类完整代码SunSpringApplicationContext.java
package com. sun. spring. ioc ;
import com. sun. spring. annotation. Autowired ;
import com. sun. spring. annotation. Component ;
import com. sun. spring. annotation. ComponentScan ;
import com. sun. spring. annotation. Scope ;
import com. sun. spring. processor. BeanPostProcessor ;
import com. sun. spring. processor. InitializingBean ;
import org. apache. commons. lang. StringUtils ;
import java. io. File ;
import java. lang. reflect. Field ;
import java. lang. reflect. InvocationTargetException ;
import java. net. URL ;
import java. util. ArrayList ;
import java. util. Enumeration ;
import java. util. List ;
import java. util. concurrent. ConcurrentHashMap ;
public class SunSpringApplicationContext {
private Class configClass;
private ConcurrentHashMap < String , BeanDefinition > beanDefinitionMap = new ConcurrentHashMap < > ( ) ;
private ConcurrentHashMap < String , Object > singletonObjects = new ConcurrentHashMap < > ( ) ;
private List < BeanPostProcessor > beanPostProcessors = new ArrayList < > ( ) ;
public SunSpringApplicationContext ( Class configClass) throws ClassNotFoundException , InstantiationException , IllegalAccessException {
this . beanDefinitionScan ( configClass) ;
Enumeration < String > keys = beanDefinitionMap. keys ( ) ;
while ( keys. hasMoreElements ( ) ) {
String beanName = keys. nextElement ( ) ;
BeanDefinition beanDefinition = beanDefinitionMap. get ( beanName) ;
if ( beanDefinition. getScope ( ) . equals ( "singleton" ) ) {
Object bean = createBean ( beanDefinition, beanName) ;
singletonObjects. put ( beanName, bean) ;
}
}
}
public void beanDefinitionScan ( Class configClass) throws ClassNotFoundException , InstantiationException , IllegalAccessException {
this . configClass = configClass;
ComponentScan componentScan = ( ComponentScan ) this . configClass. getDeclaredAnnotation ( ComponentScan . class ) ;
String path = componentScan. value ( ) ;
System . out. println ( "要扫描的包=" + 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 ( ) ;
System . out. println ( "==================================扫描所有组件==================================" ) ;
for ( File f : files) {
String absolutePath = f. getAbsolutePath ( ) ;
if ( absolutePath. endsWith ( ".class" ) ) {
String className = absolutePath. substring ( absolutePath. lastIndexOf ( "\\" ) + 1 ,
absolutePath. indexOf ( "." ) ) ;
String fullPath = path. replace ( "/" , "." ) + "." + className;
Class < ? > aClass = classLoader. loadClass ( fullPath) ;
if ( aClass. isAnnotationPresent ( Component . class ) ) {
if ( BeanPostProcessor . class . isAssignableFrom ( aClass) ) {
BeanPostProcessor beanPostProcessor = ( BeanPostProcessor ) aClass. newInstance ( ) ;
beanPostProcessors. add ( beanPostProcessor) ;
continue ;
}
System . out. println ( "这是一个Spring bean=" + aClass) ;
BeanDefinition beanDefinition = new BeanDefinition ( ) ;
Scope scopeAnnotation = aClass. getDeclaredAnnotation ( Scope . class ) ;
String scope = scopeAnnotation == null || scopeAnnotation. value ( ) . equals ( "" ) ?
"singleton" : scopeAnnotation. value ( ) ;
beanDefinition. setScope ( scope) ;
beanDefinition. setClazz ( aClass) ;
Component componentAnnotation = aClass. getDeclaredAnnotation ( Component . class ) ;
String beanName = componentAnnotation. value ( ) . equals ( "" ) ?
StringUtils . uncapitalize ( className) : componentAnnotation. value ( ) ;
beanDefinitionMap. put ( beanName, beanDefinition) ;
} else {
System . out. println ( "这不是一个Spring bean=" + aClass) ;
}
}
}
}
}
private Object createBean ( BeanDefinition beanDefinition, String beanName) {
Class clazz = beanDefinition. getClazz ( ) ;
try {
Object instance = clazz. getDeclaredConstructor ( ) . newInstance ( ) ;
for ( Field field : clazz. getDeclaredFields ( ) ) {
if ( field. isAnnotationPresent ( Autowired . class ) ) {
String name = field. getName ( ) ;
Object bean = getBean ( name) ;
field. setAccessible ( true ) ;
field. set ( instance, bean) ;
System . out. println ( instance + "依赖注入完毕!" ) ;
}
}
Object result = instance;
if ( instance instanceof InitializingBean ) {
for ( BeanPostProcessor beanPostProcessor : beanPostProcessors) {
instance = beanPostProcessor. postProcessBeforeInitialization ( instance, beanName) ;
}
( ( InitializingBean ) instance) . afterPropertiesSet ( ) ;
for ( BeanPostProcessor beanPostProcessor : beanPostProcessors) {
instance = beanPostProcessor. postProcessAfterInitialization ( instance, beanName) ;
}
}
if ( instance == null ) {
return result;
}
return instance;
} catch ( InstantiationException e) {
throw new RuntimeException ( e) ;
} catch ( IllegalAccessException e) {
throw new RuntimeException ( e) ;
} catch ( InvocationTargetException e) {
throw new RuntimeException ( e) ;
} catch ( NoSuchMethodException e) {
throw new RuntimeException ( e) ;
} catch ( Exception e) {
throw new RuntimeException ( e) ;
}
}
public Object getBean ( String name) {
if ( beanDefinitionMap. containsKey ( name) ) {
BeanDefinition beanDefinition = beanDefinitionMap. get ( name) ;
if ( "singleton" . equals ( beanDefinition. getScope ( ) ) ) {
return singletonObjects. get ( name) ;
} else {
return createBean ( beanDefinition, name) ;
}
} else {
throw new NullPointerException ( "没有该bean" ) ;
}
}
}
4.结果展示
4.该阶段完成的任务
实现初始化方法
编写初始化接口,里面有一个default的初始化方法 编写初始化实现类,重写这个初始化方法 在容器的依赖注入后添加初始化逻辑,当这个对象的类型是初始化接口的子类型的时候,就将其转换成接口类型并且调用初始化方法 后置处理器实现
编写一个后置处理器接口,里面有两个方法一个在初始化前调用,一个在初始化后调用 在组件文件夹下编写后置处理器实现类 在容器中beanDefinitionScan方法的扫描组件时添加后置处理器逻辑,如果该组件实现了后置处理器接口,则转换成后置处理器类型,并且放到ArrayList中方便查找 在容器中的createBean方法增加后置处理器逻辑,在初始化方法之前和之后遍历存储后置处理器的ArrayList并分别执行方法
阶段5—实现AOP机制&Spring底层机制总结
1.实现AOP机制
1.原理分析
2.代码实现
1.文件目录
2.编写接口SmartAnimalable.java
package com. sun. spring. component ;
public interface SmartAnimalable {
float getSum ( float i, float j) ;
float getSub ( float i, float j) ;
}
2.编写实现类SmartDog.java
package com. sun. spring. component ;
import com. sun. spring. annotation. Component ;
import com. sun. spring. processor. InitializingBean ;
@Component ( value = "smartDog" )
public class SmartDog implements SmartAnimalable , InitializingBean {
public float getSum ( float i, float j) {
float res = i + j;
System . out. println ( "SmartDog-getSum=" + res) ;
return res;
}
public float getSub ( float i, float j) {
float res = i - j;
System . out. println ( "SmartDog-getSub=" + res) ;
return res;
}
@Override
public void afterPropertiesSet ( ) throws Exception {
System . out. println ( "smartDog 被初始化!" ) ;
}
}
3.编写切面类SmartAnimalAspect.java
package com. sun. spring. component ;
public class SmartAnimalAspect {
public static void showBeginLog ( ) {
System . out. println ( "前置通知" ) ;
}
public static void showSuccessLog ( ) {
System . out. println ( "返回通知" ) ;
}
}
4.修改SunBeanPostProcessor.java对SmartDog的getSum方法进行动态代理
package com. sun. spring. component ;
import com. sun. spring. annotation. Component ;
import com. sun. spring. processor. BeanPostProcessor ;
import java. lang. reflect. InvocationHandler ;
import java. lang. reflect. Method ;
import java. lang. reflect. Proxy ;
@Component
public class SunBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization ( Object bean, String beanName) {
System . out. println ( "\n后置处理器postProcessBeforeInitialization被调用 bean类型=" + bean. getClass ( ) + "bean名字=" + beanName) ;
if ( bean instanceof Car ) {
System . out. println ( "后置处理器发现这个类型是Car类型" ) ;
}
return bean;
}
@Override
public Object postProcessAfterInitialization ( Object bean, String beanName) {
System . out. println ( "后置处理器postProcessAfterInitialization被调用 bean类型=" + bean. getClass ( ) + "bean名字=" + beanName) ;
if ( "smartDog" . equals ( beanName) ) {
ClassLoader classLoader = bean. getClass ( ) . getClassLoader ( ) ;
Class < ? > [ ] interfaces = bean. getClass ( ) . getInterfaces ( ) ;
InvocationHandler invocationHandler = new InvocationHandler ( ) {
@Override
public Object invoke ( Object proxy, Method method, Object [ ] args) throws Throwable {
Object result = null ;
if ( "getSum" . equals ( method. getName ( ) ) ) {
SmartAnimalAspect . showBeginLog ( ) ;
result = method. invoke ( bean, args) ;
SmartAnimalAspect . showSuccessLog ( ) ;
} else {
result = method. invoke ( bean, args) ;
}
return result;
}
} ;
return Proxy . newProxyInstance ( classLoader, interfaces, invocationHandler) ;
}
return bean;
}
}
5.启动类
package com. sun. spring ;
import com. sun. spring. component. MonsterService ;
import com. sun. spring. component. SmartAnimalable ;
import com. sun. spring. ioc. SunSpringApplicationContext ;
import com. sun. spring. ioc. SunSpringConfig ;
public class AppMain {
public static void main ( String [ ] args) throws ClassNotFoundException , InstantiationException , IllegalAccessException {
SunSpringApplicationContext ioc = new SunSpringApplicationContext ( SunSpringConfig . class ) ;
Object bean01 = ioc. getBean ( "monsterDao" ) ;
MonsterService bean = ( MonsterService ) ioc. getBean ( "monsterService" ) ;
System . out. println ( "==================================测试依赖注入调用方法==================================" ) ;
bean. m1 ( ) ;
System . out. println ( "==================================测试AOP==================================" ) ;
SmartAnimalable proxy = ( SmartAnimalable ) ioc. getBean ( "smartDog" ) ;
proxy. getSub ( 4 , 1 ) ;
proxy. getSum ( 2 , 4 ) ;
}
}
6.结果展示
3.该阶段完成的任务
编写接口,编写实现类并将实例交给Spring容器管理,编写切面类 后置处理器中进行动态代理操作,这里是对SmartDog类型的getSum方法进行动态代理
首先判断beanName是不是smartDog 如果是则进行动态代理,invoke方法中先判断当前执行的方法是不是getSum 如果是getSum则插入前置通知和返回通知,如果不是则正常执行这个方法
2.Spring底层机制总结
1.bean的生命周期
反射创建bean对象 依赖注入 初始化bean getBean 销毁bean
2.Spring容器的执行流程
获取容器对象 读取配置文件,得到要扫描的包 扫描包下的组件,将bean定义信息放到Map中 如果是单例
反射创建bean对象,放到单例池中 依赖注入(调用getBean) 初始化bean
初始化容器前调用后置处理器的before方法 初始化容器之后调用后置处理器的after方法 如果是多例
getBean阶段
如果是单例
如果是多例
反射创建bean对象 依赖注入(调用getBean) 初始化bean
初始化容器前调用后置处理器的before方法 初始化容器之后调用后置处理器的after方法 得到bean对象 销毁bean
3.动态代理和AOP的区别
动态代理:针对的是 某个对象 的所有方法 AOP:针对的是 某些类型 的所有对象 的具体方法
4.关于后置处理器 + 动态代理的理解
后置处理器作用于Spring容器中所有类型,所有对象 的初始化方法 getBean得到的就是后置处理器返回的bean 当进入到后置处理器的时候
获取切面类的所有信息 将切入表达式与当前bean对象进行对比,只要类型匹配 就进行动态代理 使用动态代理进一步筛选要代理的方法 ,并根据不同的通知执行不同的操作,返回动态代理对象 如果是不需要代理的方法,就不进行额外操作
5.AOP的使用方式
编写接口,接口对象(注解)(用于展示AOP的效果,因为没有对象) 编写切面类(注解),切面对象(注解) 通知 + 切点 配置beans.xnl
具体使用
获取针对接口类型 的代理对象(通过id或者接口类型获取) 使用代理对象调用接口的方法 四种通知