public class User{
private String id;
private String name;
private String password;
private Date birthday;
//ignore other properties...
//ignore setter getter method
}
public interface IUserDao{
public void add(User user);
public void delete(User user);
public List<User> findAll();
}
public class UserDaoImpl{
public void add(User user){
//ignore the implementation
}
public void delete(User user){
//ignore the implementation
}
public List<User> findAll(){
//ignore the implementation
}
}
public class UserController{
private IUserDao userDao = new UserDaoImpl();
@RequestMapping("/user/add")
public void add(User user){
userDao.add(user);
}
@RequestMapping("/user/delete")
public void delete(User user){
userDao.add(user);
}
@RequestMapping("/user/findAll")
public void findAll(User user){
List<User> allUser = userDao.findAll();
}
} 在这里面,UserController调用private IUserDao userDao = new UserDaoImpl()来初始化userDao。由于java是一门编译语言,也就是将.java变成.class的过程。在这个过程中捆绑了IUserDao的实现,也就是UserDaoImpl。虽然开发者使用了面向接口编程的风格来书写代码,但是还是和UserDaoImpl捆绑在了一起。如果后期开发中,为IUserDao提供另外一种实现,比如:将orm框架由mybatis换成了hibernate,那么就需要修改源码UserController的实现。传统模式中,一个类依赖的其他类都由自己维护,需要什么类,就new一个。这种开发方式的耦合性比较高,不利于后期的维护。那么既然这种方式不好,那么有没有一种其他办法来解决这个问题呢?没错,IOC可以非常好的解决这个问题。public class User{
private String id;
private String name;
private String password;
private Date birthday;
//ignore other properties...
//ignore setter getter method<span style="white-space:pre"> </span>
}
public interface IUserDao{
public void add(User user);
public void delete(User user);
public List<User> findAll();
}
@Repository
public class UserDaoImpl{
public void add(User user){
//ignore the implementation
}
public void delete(User user){
//ignore the implementation
}
public List<User> findAll(){
//ignore the implementation
}
}
@Controller
public class UserController{
//主动注入这个类
@Autowired
private IUserDao userDao userDao;
@RequestMapping("/user/add")
public void add(User user){
userDao.add(user);
}
@RequestMapping("/user/delete")
public void delete(User user){
userDao.add(user);
}
@RequestMapping("/user/findAll")
public void findAll(User user){
List<User> allUser = userDao.findAll();
}
}
从代码中我们可以看到,这两份代码几乎是一样的,就只是去掉了userDao的实现类,在userDao变量中加入了@Autowired注解而已。没错,这就是spring的厉害之处,因为spring是一种无侵入式的轻量级框架。那么spring是如何实现控制反转的呢?下面先给出一个spring ioc图/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory;
import org.springframework.beans.BeansException;
/**
* The root interface for accessing a Spring bean container.
* This is the basic client view of a bean container;
* further interfaces such as {@link ListableBeanFactory} and
* {@link org.springframework.beans.factory.config.ConfigurableBeanFactory}
* are available for specific purposes.
*
* <p>This interface is implemented by objects that hold a number of bean definitions,
* each uniquely identified by a String name. Depending on the bean definition,
* the factory will return either an independent instance of a contained object
* (the Prototype design pattern), or a single shared instance (a superior
* alternative to the Singleton design pattern, in which the instance is a
* singleton in the scope of the factory). Which type of instance will be returned
* depends on the bean factory configuration: the API is the same. Since Spring
* 2.0, further scopes are available depending on the concrete application
* context (e.g. "request" and "session" scopes in a web environment).
*
* <p>The point of this approach is that the BeanFactory is a central registry
* of application components, and centralizes configuration of application
* components (no more do individual objects need to read properties files,
* for example). See chapters 4 and 11 of "Expert One-on-One J2EE Design and
* Development" for a discussion of the benefits of this approach.
*
* <p>Note that it is generally better to rely on Dependency Injection
* ("push" configuration) to configure application objects through setters
* or constructors, rather than use any form of "pull" configuration like a
* BeanFactory lookup. Spring's Dependency Injection functionality is
* implemented using this BeanFactory interface and its subinterfaces.
*
* <p>Normally a BeanFactory will load bean definitions stored in a configuration
* source (such as an XML document), and use the {@code org.springframework.beans}
* package to configure the beans. However, an implementation could simply return
* Java objects it creates as necessary directly in Java code. There are no
* constraints on how the definitions could be stored: LDAP, RDBMS, XML,
* properties file, etc. Implementations are encouraged to support references
* amongst beans (Dependency Injection).
*
* <p>In contrast to the methods in {@link ListableBeanFactory}, all of the
* operations in this interface will also check parent factories if this is a
* {@link HierarchicalBeanFactory}. If a bean is not found in this factory instance,
* the immediate parent factory will be asked. Beans in this factory instance
* are supposed to override beans of the same name in any parent factory.
*
* <p>Bean factory implementations should support the standard bean lifecycle interfaces
* as far as possible. The full set of initialization methods and their standard order is:<br>
* 1. BeanNameAware's {@code setBeanName}<br>
* 2. BeanClassLoaderAware's {@code setBeanClassLoader}<br>
* 3. BeanFactoryAware's {@code setBeanFactory}<br>
* 4. ResourceLoaderAware's {@code setResourceLoader}
* (only applicable when running in an application context)<br>
* 5. ApplicationEventPublisherAware's {@code setApplicationEventPublisher}
* (only applicable when running in an application context)<br>
* 6. MessageSourceAware's {@code setMessageSource}
* (only applicable when running in an application context)<br>
* 7. ApplicationContextAware's {@code setApplicationContext}
* (only applicable when running in an application context)<br>
* 8. ServletContextAware's {@code setServletContext}
* (only applicable when running in a web application context)<br>
* 9. {@code postProcessBeforeInitialization} methods of BeanPostProcessors<br>
* 10. InitializingBean's {@code afterPropertiesSet}<br>
* 11. a custom init-method definition<br>
* 12. {@code postProcessAfterInitialization} methods of BeanPostProcessors
*
* <p>On shutdown of a bean factory, the following lifecycle methods apply:<br>
* 1. DisposableBean's {@code destroy}<br>
* 2. a custom destroy-method definition
*
*/
public interface BeanFactory {
/**
* Used to dereference a {@link FactoryBean} instance and distinguish it from
* beans <i>created</i> by the FactoryBean. For example, if the bean named
* {@code myJndiObject} is a FactoryBean, getting {@code &myJndiObject}
* will return the factory, not the instance returned by the factory.
*/
String FACTORY_BEAN_PREFIX = "&";
/**
* Return an instance, which may be shared or independent, of the specified bean.
* <p>This method allows a Spring BeanFactory to be used as a replacement for the
* Singleton or Prototype design pattern. Callers may retain references to
* returned objects in the case of Singleton beans.
* <p>Translates aliases back to the corresponding canonical bean name.
* Will ask the parent factory if the bean cannot be found in this factory instance.
* @param name the name of the bean to retrieve
* @return an instance of the bean
* @throws NoSuchBeanDefinitionException if there is no bean definition
* with the specified name
* @throws BeansException if the bean could not be obtained
*/
Object getBean(String name) throws BeansException;
/**
* Return an instance, which may be shared or independent, of the specified bean.
* <p>Behaves the same as {@link #getBean(String)}, but provides a measure of type
* safety by throwing a BeanNotOfRequiredTypeException if the bean is not of the
* required type. This means that ClassCastException can't be thrown on casting
* the result correctly, as can happen with {@link #getBean(String)}.
* <p>Translates aliases back to the corresponding canonical bean name.
* Will ask the parent factory if the bean cannot be found in this factory instance.
* @param name the name of the bean to retrieve
* @param requiredType type the bean must match. Can be an interface or superclass
* of the actual class, or {@code null} for any match. For example, if the value
* is {@code Object.class}, this method will succeed whatever the class of the
* returned instance.
* @return an instance of the bean
* @throws NoSuchBeanDefinitionException if there is no such bean definition
* @throws BeanNotOfRequiredTypeException if the bean is not of the required type
* @throws BeansException if the bean could not be created
*/
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
/**
* Return the bean instance that uniquely matches the given object type, if any.
* @param requiredType type the bean must match; can be an interface or superclass.
* {@code null} is disallowed.
* <p>This method goes into {@link ListableBeanFactory} by-type lookup territory
* but may also be translated into a conventional by-name lookup based on the name
* of the given type. For more extensive retrieval operations across sets of beans,
* use {@link ListableBeanFactory} and/or {@link BeanFactoryUtils}.
* @return an instance of the single bean matching the required type
* @throws NoSuchBeanDefinitionException if no bean of the given type was found
* @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found
* @since 3.0
* @see ListableBeanFactory
*/
<T> T getBean(Class<T> requiredType) throws BeansException;
/**
* Return an instance, which may be shared or independent, of the specified bean.
* <p>Allows for specifying explicit constructor arguments / factory method arguments,
* overriding the specified default arguments (if any) in the bean definition.
* @param name the name of the bean to retrieve
* @param args arguments to use if creating a prototype using explicit arguments to a
* static factory method. It is invalid to use a non-null args value in any other case.
* @return an instance of the bean
* @throws NoSuchBeanDefinitionException if there is no such bean definition
* @throws BeanDefinitionStoreException if arguments have been given but
* the affected bean isn't a prototype
* @throws BeansException if the bean could not be created
* @since 2.5
*/
Object getBean(String name, Object... args) throws BeansException;
/**
* Does this bean factory contain a bean definition or externally registered singleton
* instance with the given name?
* <p>If the given name is an alias, it will be translated back to the corresponding
* canonical bean name.
* <p>If this factory is hierarchical, will ask any parent factory if the bean cannot
* be found in this factory instance.
* <p>If a bean definition or singleton instance matching the given name is found,
* this method will return {@code true} whether the named bean definition is concrete
* or abstract, lazy or eager, in scope or not. Therefore, note that a {@code true}
* return value from this method does not necessarily indicate that {@link #getBean}
* will be able to obtain an instance for the same name.
* @param name the name of the bean to query
* @return whether a bean with the given name is present
*/
boolean containsBean(String name);
/**
* Is this bean a shared singleton? That is, will {@link #getBean} always
* return the same instance?
* <p>Note: This method returning {@code false} does not clearly indicate
* independent instances. It indicates non-singleton instances, which may correspond
* to a scoped bean as well. Use the {@link #isPrototype} operation to explicitly
* check for independent instances.
* <p>Translates aliases back to the corresponding canonical bean name.
* Will ask the parent factory if the bean cannot be found in this factory instance.
* @param name the name of the bean to query
* @return whether this bean corresponds to a singleton instance
* @throws NoSuchBeanDefinitionException if there is no bean with the given name
* @see #getBean
* @see #isPrototype
*/
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
/**
* Is this bean a prototype? That is, will {@link #getBean} always return
* independent instances?
* <p>Note: This method returning {@code false} does not clearly indicate
* a singleton object. It indicates non-independent instances, which may correspond
* to a scoped bean as well. Use the {@link #isSingleton} operation to explicitly
* check for a shared singleton instance.
* <p>Translates aliases back to the corresponding canonical bean name.
* Will ask the parent factory if the bean cannot be found in this factory instance.
* @param name the name of the bean to query
* @return whether this bean will always deliver independent instances
* @throws NoSuchBeanDefinitionException if there is no bean with the given name
* @since 2.0.3
* @see #getBean
* @see #isSingleton
*/
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
/**
* Check whether the bean with the given name matches the specified type.
* More specifically, check whether a {@link #getBean} call for the given name
* would return an object that is assignable to the specified target type.
* <p>Translates aliases back to the corresponding canonical bean name.
* Will ask the parent factory if the bean cannot be found in this factory instance.
* @param name the name of the bean to query
* @param targetType the type to match against
* @return {@code true} if the bean type matches,
* {@code false} if it doesn't match or cannot be determined yet
* @throws NoSuchBeanDefinitionException if there is no bean with the given name
* @since 2.0.1
* @see #getBean
* @see #getType
*/
boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException;
/**
* Determine the type of the bean with the given name. More specifically,
* determine the type of object that {@link #getBean} would return for the given name.
* <p>For a {@link FactoryBean}, return the type of object that the FactoryBean creates,
* as exposed by {@link FactoryBean#getObjectType()}.
* <p>Translates aliases back to the corresponding canonical bean name.
* Will ask the parent factory if the bean cannot be found in this factory instance.
* @param name the name of the bean to query
* @return the type of the bean, or {@code null} if not determinable
* @throws NoSuchBeanDefinitionException if there is no bean with the given name
* @since 1.1.2
* @see #getBean
* @see #isTypeMatch
*/
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
/**
* Return the aliases for the given bean name, if any.
* All of those aliases point to the same bean when used in a {@link #getBean} call.
* <p>If the given name is an alias, the corresponding original bean name
* and other aliases (if any) will be returned, with the original bean name
* being the first element in the array.
* <p>Will ask the parent factory if the bean cannot be found in this factory instance.
* @param name the bean name to check for aliases
* @return the aliases, or an empty array if none
* @see #getBean
*/
String[] getAliases(String name);
}
当然,仅仅这几个普通的接口肯定是无法定义整个spring ioc需要的类的,但是BeanFactory作为基类,保持接口的精简是非常必要的,其他的BeanFactory根据特性继承该接口即可,下面贴出关于整个BeanFactory的继承体系。|
class |
|
|
name |
类名 |
|
scope |
生存周期 |
|
constructor arguments |
构造参数 |
|
properties |
属性 |
|
autowiring mode |
注入模式(byName, byType, auto) |
|
lazy-initialization mode |
延迟加载模式 |
|
initialization method |
初始化时调用的方法 |
|
destruction method |
摧毁时调用的方法 |
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文:http://blog.csdn.net/u010469003/article/details/47134533