当我们在Appconfig上不加@Confaugration时,如果
UserService.java
public class UserService {
public UserService(){
System.out.println("init UserService");
}
}
OrederService.java
public class OrderService {
}
Appconfig.java
//@Configuration
@ComponentScan("com.suntong.hello")
public class Appconfig {
@Bean
public UserService userService(){
return new UserService();
}
@Bean
public OrderService orderService(){
userService();
return new OrderService();
}
}
Test.java
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext annotationConfigApplicationContext =
new AnnotationConfigApplicationContext(Appconfig.class);
//这句没有也行,不会影响初始化
System.out.println(annotationConfigApplicationContext.getBean(OrderService.class).getClass().getName());
}
}
此时没有@Configuration注解,我们
打印出来的时两次init UserService
放开注解
就剩一次了,说明UserService被改变了
我们获取一下Appconfig类,看一看加上@Configuration后,Appconfig还是不是原先的类
Appconfig appconfig = annotationConfigApplicationContext.getBean(Appconfig.class);
断点调试
已经被代理了
UserService和OrderService还是原先的模样
如何实现一个cglib代理?
可以参考Spring中的代码
ctrl+shift+alt+N 查找类 ConfigurationClassPostPrpcessor
再进入ConfigurationClassEnhancer
ctrl+F12查找方法
/**
* Creates a new CGLIB {@link Enhancer} instance.
*/
private Enhancer newEnhancer(Class> superclass, ClassLoader classLoader) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(superclass);
enhancer.setInterfaces(new Class>[] {EnhancedConfiguration.class});
enhancer.setUseFactory(false);
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
enhancer.setCallbackFilter(CALLBACK_FILTER);
enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
return enhancer;
}
Enhancer类再cglib包下
父类的话,想代理哪个类就用哪个类
第三行第四行不用接口,不需要
setStrategy不需要,增强属性
后面两个为过滤方法,就是增强
setCallbackFilter复杂,我们只用setCallBack
package org.springframework.cglib.proxy;
public interface Callback {
}
Callback为一个接口
ctrl+alt+B找到实现类
package org.springframework.cglib.proxy;
import java.lang.reflect.Method;
public interface MethodInterceptor extends Callback {
Object intercept(Object var1, Method var2, Object[] var3, MethodProxy var4) throws Throwable;
}
还是一个接口
自己实现
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class SuntongMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("interceptor cglib");
return methodProxy.invokeSuper(o,objects);
}
}
最后的代理生成,调用UserService新增的方法query
public static void main(String[] args) {
// AnnotationConfigApplicationContext annotationConfigApplicationContext =
// new AnnotationConfigApplicationContext(Appconfig.class);
// Appconfig appconfig = annotationConfigApplicationContext.getBean(Appconfig.class);
// UserService userService = annotationConfigApplicationContext.getBean(UserService.class);
// OrderService orderService = annotationConfigApplicationContext.getBean(OrderService.class);
// System.out.println(annotationConfigApplicationContext.getBean(OrderService.class).getClass().getName());
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserService.class);
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setCallback(new SuntongMethodInterceptor());
UserService userService = (UserService) enhancer.create();
userService.query();
}
完成代理增强
小结
所以之前OrderService中的userService方法根本就没有调用到UserService
什么时候解析的@Configuration
到AnnotationConfigApplicationContext
的refresh
方法invokeBeanFactoryPostProcessors(beanFactory);
方法下invokeBeanFactoryPostProcessors(beanFactory
, getBeanFactoryPostProcessors())
方法
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);
执行BeanFactoryPostProcessor
的回调
前面执行的时BeanFactoryPostProcessor
子类BeanDefinitionRegistryPostProcessor
的回调
点进去
for (BeanFactoryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanFactory(beanFactory);
}
点进去
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
int factoryId = System.identityHashCode(beanFactory);
if (this.factoriesPostProcessed.contains(factoryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + beanFactory);
}
this.factoriesPostProcessed.add(factoryId);
if (!this.registriesPostProcessed.contains(factoryId)) {
// BeanDefinitionRegistryPostProcessor hook apparently not supported...
// Simply call processConfigurationClasses lazily at this point then.
processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
}
enhanceConfigurationClasses(beanFactory);
}
点进去enhanceConfigurationClasses(beanFactory)
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
Map configBeanDefs = new LinkedHashMap();
for (String beanName : beanFactory.getBeanDefinitionNames()) {
BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef)) {
if (!(beanDef instanceof AbstractBeanDefinition)) {
throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +
beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
}
configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
}
}
加了@Configuration的类才能进入if判断isFullConfigurationClass
全注解
加条件断点
BeanDefinition是用来描述Bean的
进入if判断(因为有@Configuration注解)
回到之前的Map,因为spring类有很多,会对map进行遍历看是否有注解
点进去
public Class> enhance(Class> configClass, ClassLoader classLoader) {
if (EnhancedConfiguration.class.isAssignableFrom(configClass)) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("Ignoring request to enhance %s as it has " +
"already been enhanced. This usually indicates that more than one " +
"ConfigurationClassPostProcessor has been registered (e.g. via " +
"). This is harmless, but you may " +
"want check your configuration and remove one CCPP if possible",
configClass.getName()));
}
return configClass;
}
Class> enhancedClass = createClass(newEnhancer(configClass, classLoader));
if (logger.isDebugEnabled()) {
logger.debug(String.format("Successfully enhanced %s; enhanced class name is: %s",
configClass.getName(), enhancedClass.getName()));
}
return enhancedClass;
}
if (EnhancedConfiguration.class.isAssignableFrom(configClass))
判断是否被代理过
因为底层会添加一个代理接口
这时候就很熟悉了,这里就是刚才我们自己实现的代理用的代码
打上断点
BeanFactoryAwareGeneratorStrategy
中有一个transfom
方法增强属性
看一下过滤器
enhancer.setCallbackFilter(CALLBACK_FILTER);
3个过滤器,用了一个数组
private static final Callback[] CALLBACKS = new Callback[] {
new BeanMethodInterceptor(),
//设置一个beanFactory
new BeanFactoryAwareMethodInterceptor(),
NoOp.INSTANCE
};
看第一个,点进去
@Override
public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
MethodProxy cglibMethodProxy) throws Throwable {
一个判断
if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
这里就能看开始的问题了,比如第一次访问就new一个对象,不然就else
而Spring看执行的方法名是否相同,相同就new,不相同就getBean
比如之前我们的方法名时orderService,而内部要调用userService,所以直接getBean了,就没有实例对象
if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
// The factory is calling the bean method in order to instantiate and register the bean
// (i.e. via a getBean() call) -> invoke the super implementation of the method to actually
// create the bean instance.
if (BeanFactoryPostProcessor.class.isAssignableFrom(beanMethod.getReturnType())) {
logger.warn(String.format("@Bean method %s.%s is non-static and returns an object " +
"assignable to Spring's BeanFactoryPostProcessor interface. This will " +
"result in a failure to process annotations such as @Autowired, " +
"@Resource and @PostConstruct within the method's declaring " +
"@Configuration class. Add the 'static' modifier to this method to avoid " +
"these container lifecycle issues; see @Bean javadoc for complete details.",
beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName()));
}
return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
}
else {
// The user (i.e. not the factory) is requesting this bean through a
// call to the bean method, direct or indirect. The bean may have already been
// marked as 'in creation' in certain autowiring scenarios; if so, temporarily
// set the in-creation status to false in order to avoid an exception.
boolean alreadyInCreation = beanFactory.isCurrentlyInCreation(beanName);
try {
if (alreadyInCreation) {
beanFactory.setCurrentlyInCreation(beanName, false);
}
Object beanInstance = (!ObjectUtils.isEmpty(beanMethodArgs) ?
beanFactory.getBean(beanName, beanMethodArgs) : beanFactory.getBean(beanName));
if (beanInstance != null && !ClassUtils.isAssignableValue(beanMethod.getReturnType(), beanInstance)) {
String msg = String.format("@Bean method %s.%s called as a bean reference " +
"for type [%s] but overridden by non-compatible bean instance of type [%s].",
beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName(),
beanMethod.getReturnType().getName(), beanInstance.getClass().getName());
try {
BeanDefinition beanDefinition = beanFactory.getMergedBeanDefinition(beanName);
msg += " Overriding bean of same name declared in: " + beanDefinition.getResourceDescription();
}
catch (NoSuchBeanDefinitionException ex) {
// Ignore - simply no detailed message then.
}
throw new IllegalStateException(msg);
}
return beanInstance;
}
finally {
if (alreadyInCreation) {
beanFactory.setCurrentlyInCreation(beanName, true);
}
}
}
返回父类的方法
点这个,跳过去
又实例了一个OrderService
再来第三遍
直接进入了else
判断是否正在创建
已经创建完了
这样就不会二次创建了
FactoryBean和BeanFactory
BeanFactory就是产生存储Bean的容器。
FactoryBean是一种特殊的bean,它的getObject方法可以返回一个对象,如果你用过spring-mybatis的话,你有没有想过为什么一个mapper接口最后可以变成一个对象进行数据库的操作?原因是mybatis底层把我们的mapper定义成一个FactoryBean,然后在getObject方法中通过动态代理生成一个实力可操作的代理对象保存在Factory容器中。
如果给UserService加上static呢
还是两次