spring详解

1.搭建spring运行环境
    1.1.导入jar包
        spring包:
            SPRING_HOME/dist/org.springframework.asm-3.1.3.RELEASE.jar
            SPRING_HOME/dist/org.springframework.beans-3.1.3.RELEASE.jar
            SPRING_HOME/dist/org.springframework.context-3.1.3.RELEASE.jar
            SPRING_HOME/dist/org.springframework.core-3.1.3.RELEASE.jar
            SPRING_HOME/dist/org.springframework.expression-3.1.3.RELEASE.jar
        log4j包:
            log4j-1.2.17.jar
        commons-logging:
            commons-logging-1.1.1.jar
    1.2.加入配置文件
        SPRING_HOME/project/.../...context.xml(applicationContext-bean.xml)
        最简单的配置文件:
            <?xml version="1.0" encoding="UTF-8"?>
            <beans xmlns="http://www.springframework.org/schema/beans"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="http://www.springframework.org/schema/beans
                    http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
                <bean id="person" class="com.spring.pojo.Person">
                    <!-- bean 的内容 -->
                </bean>
            </beans>
        需要使用annotation的配置文件:
            <?xml version="1.0" encoding="UTF-8"?>
            <beans xmlns="http://www.springframework.org/schema/beans"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xmlns:context="http://www.springframework.org/schema/context"
                xsi:schemaLocation="http://www.springframework.org/schema/beans
                    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                    http://www.springframework.org/schema/context
                    http://www.springframework.org/schema/context/spring-context-2.5.xsd">
            </beans>
        需要使用aspect的配置文件:
            <?xml version="1.0" encoding="UTF-8"?>
                <beans xmlns="http://www.springframework.org/schema/beans"
                       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                       xmlns:context="http://www.springframework.org/schema/context"
                       xmlns:aop="http://www.springframework.org/schema/aop"     
                       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context-2.5.xsd
                           http://www.springframework.org/schema/aop
                           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
                    <aop:aspectj-autoproxy/>
                </beans>
    1.3.测试运行环境
        @Test
        public void testBean() throws Exception {
            ApplicationContext ac = new ClassPathXmlApplicationContext(
                    new String[] { "applicationContext-bean.xml" });
            Person p = (Person) ac.getBean("person");
            System.out.println(p.getClass().getName());
            p.getClass().newInstance().say();
        }
2.spring中创建bean实例的3中方式
    2.1.使用构造器实例化(最常用的一种方式)
        <bean id="person" class="com.spring.pojo.Person"></bean>
    2.2.使用静态工厂方法实例化
        public class PersonFactory {
            public static Person createPerson(){//注意,该方法应该是static的
                return new Person();
            }
        }
        //注意class对应的名称应该是factory的类。
        <bean id="person2" class="com.spring.pojo.PersonFactory" factory-method="createPerson">
            <!-- bean 的内容 -->
        </bean>
    2.3.使用实例化工厂方法实例化
        先实例化一个工厂bean,在使用该工厂bean去实例化需要的bean
        public class PersonFactory {
            public Person createPerson(){//注意,该方法不是static的
                return new Person();
            }
        }
        //注意class对应的名称应该是factory的类。factor-bean对应的是factoryBean的id。
        <bean id="personFactory" class="com.spring.pojo.PersonFactory"></bean>
        <bean id="person3" factory-bean="personFactory" factory-method="createPerson"></bean>
3.spring中bean的作用域(scope)
    .singleton 默认情况得到的是相同的对象(单实例)
        <bean id="person" class="com.spring.pojo.Person"></bean>//默认可以不用写
        Person p1 = (Person) ac.getBean("person");
        Person p2 = (Person) ac.getBean("person");
        System.out.println(p1 == p2);//true
    .prototype 每次从容器中得到的都是新的对象
        <bean id="person" class="com.spring.pojo.Person" scope="prototype"></bean>
        System.out.println(p1 == p2);//false
    //默认情况下lazy-init="false",不延迟加载。可以设置lazy-init="true";
    //下面是web应用中使用到。
    .request
    .session
    .global session(application)
4.spring中管理bean的生命周期
    4.1.lazy-init="default"(默认情况下)
        当scope="singleton"时,在初始化spring容器的时候,在加载完xml配置文件后会实例化所有配置文件中的class
        当scopt="prototype"时,在getBean()方法调用的时候才会进行实例化
    4.2.lazy-init="true"
        此时,无论scope的值为什么,都会延迟初始化,在getBean()时才实例化,一般不推荐使用。
    4.3.实例化之后执行init()方法(init-method)
        <bean id="person" class="com.spring.pojo.Person" lazy-init="false" init-method="init"></bean>
    4.4.实例对象被摧毁是执行destroy()方法(destroy-method)
        <bean id="person" class="com.spring.pojo.Person" lazy-init="false" destroy-method="destroy"></bean>
        当AbstractApplicationContext执行.close()或者.destroy()时调运。
        输出结果顺序:正在实例化Person对象    正在初始化。。。正在摧毁。。。
5.spring中的bean注入依赖对象
    5.1.使用属性的Setter方法注入。
        public class PersonServiceImpl implements PersonService {
            private String name;
            private PersonDao personDao;
            private Set<String> sets = new HashSet<String>();
            private List<String> lists = new ArrayList<String>();
            private Map<Integer, String> maps = new HashMap<Integer, String>();
            private Properties properties = new Properties();
            //setter/getter
        }
       
        基本类型属性的注入:(使用value属性)
            <bean id="personService" class="com.spring.service.impl.PersonServiceImpl">
                <property name="name" value="gusi"></property>           
            </bean>
        其他bean属性的注入:
            方法一:使用ref属性引用其他bean方式(通过反射,使用setXxx()方法注入)
                <bean id="personDao" class="com.spring.dao.impl.PersonDaoImpl"></bean>
                <bean id="personService" class="com.spring.service.impl.PersonServiceImpl">
                    <property name="personDao" ref="personDao"></property>
                </bean>
            方法二:使用内部bean注入(该bean不能被其他bean使用)
                <bean id="personService" class="com.spring.service.impl.PersonServiceImpl">
                    <property name="personDao">
                        <bean class="com.spring.dao.impl.PersonDaoImpl"></bean>
                    </property>       
                </bean>
        注入各种集合:
            set集合:
                <property name="sets">
                    <set>
                        <value>first</value>
                        <value>third</value>
                        <value>second</value>
                    </set>
                </property>
            list集合:
                <property name="lists">
                    <list>
                        <value>第一个</value>
                        <value>第二个</value>
                        <value>第三个</value>
                    </list>
                </property>
            map集合:
                <property name="maps">
                    <map>
                        <entry key="1" value="value1"></entry>
                        <entry key="2" value="value2"></entry>
                        <entry key="3" value="value3"></entry>
                    </map>
                </property>
            Properties对象:
                <property name="properties">
                    <props>
                        <prop key="1">java</prop>
                        <prop key="2">web</prop>
                    </props>
                </property>
    5.2.使用带参构造器注入。
        public class PersonServiceImpl2 implements PersonService {
            private String name;
            private PersonDao personDao;
            public PersonServiceImpl2(String name, PersonDao personDao) {
                this.name = name;
                this.personDao = personDao;
            }
        }    //可以没有setter方法
        xml配置文件
            <bean id="personDao" class="com.spring.dao.impl.PersonDaoImpl"></bean>
            <bean id="personService2" class="com.spring.service.impl.PersonServiceImpl2">
                <constructor-arg index="0" value="dyy"></constructor-arg>
                <constructor-arg index="1" type="com.spring.dao.PersonDao" ref="personDao"></constructor-arg>
            </bean>
        注意:index属性,type属性, value属性,ref属性的使用。
6.spring中使用注解(annotation)的方式装配属性
    step1.修改配置文件:
        加入新的命名空间:xmlns:context="http://www.springframework.org/schema/context"
        加入新的约束文件:http://www.springframework.org/schema/context
                          http://www.springframework.org/schema/context/spring-context-2.5.xsd"
        加入注册处理器配置:<context:annotation-config/>//该配置隐式注册了多个对注解进行解析处理的处理器。
        完整的配置文件:
            <?xml version="1.0" encoding="UTF-8"?>
            <beans xmlns="http://www.springframework.org/schema/beans"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xmlns:context="http://www.springframework.org/schema/context"
                xsi:schemaLocation="http://www.springframework.org/schema/beans
                    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                    http://www.springframework.org/schema/context
                    http://www.springframework.org/schema/context/spring-context-2.5.xsd">
                <context:annotation-config/>
            </beans>
    step2.添加需要的jar包:
        lib\j2ee/common-annotations.jar
    @Autowire:默认按类型装配。可以和@Qualifier一起使用按名称装配,还可以设置required属性是否可以为null。
    @Resource:默认按名称装配,当找不到对应的名称时,就按类型装配。
              可以使用一个name属性标识名称,若没找到name属性的bean,默认取字段的名称作为name的值。
    都可以用在字段上和setter方法上。
7.spring中的属性的自动装配(使用autowire属性)
    <bean id="" class="" autowire="default"></bean>
    autowire的取值和含义:    byType:按类型装配,可以根据属性的类型,在容器中寻找跟该类型匹配的bean。
                            byName:按名称装配,可以根据属性的名称,在容器中寻找跟该属性名相同的bean。
                            bonstructor:与byType类似,用于构造器参数。
                            autodetect:通过自省机制(introspection),来决定使用constructor还是byType方式。
                                       若发现默认构造器,那么将使用byType方式。
    注意:必须和@Autowire标注配合使用。不推荐使用,可能发生一些不期望的结果。       
8.spring中自动扫描和管理bean
    在使用annotation的环境下注册处理器:<context:component-scan base-package="要扫描的包名" />
    在class上面配置不同的标注:
        @Service(idName) 标注业务层组件(如Service层)
        @Controller(idName) 标注控制层组件(如struts中的Action上)
        @Repository(idName)  标注数据访问组件(如 Dao层)
        @Component 泛指组件,当组件不好归类的时候,使用这个标注进行标注。
        目前,这四个标注没有特别的区别。功能一样。
    访问自动管理的bean:
        使用getBean(idName/className)时,如果没有指定idName,那么就是使用默认的ClassName首字母小写。
    设置bean的范围:
        在类标注后面接着使用@Scope标注,
        @Scope( prototype/singleton(默认))。
    设置初始化/摧毁方法:
        在标注类的初始化方法上使用@PostConstruct,不是spring自己的注解,是ejb3的注解
            @PostConstruct
            public void init(){}
        在标注类的摧毁方法上使用@PreDestroy标注
            @PreDestroy
            public viod destroy(){}
9.spring中使用AOP
    代理模式:proxy我们不直接调运目标对象,我们直接调运代理对象,让代理对象去调运目标对象。
    我们就可以在调运代理对象的时候做一些权限处理。
        方式1:使用jdk提供的代理对象(代理对象需要实现InvocationHandler接口,目标对象必须实现其他接口)
            public class JDKProxyFactory implements InvocationHandler {
                private Object targetObject;//需要调运的目标对象
                /**
                 * 返回创建好的代理对象
                 * @param targetObject
                 * @return
                 */
                public Object createProxyInstance(Object targetObject) {
                    this.targetObject = targetObject;
                    //loader - 定义代理类的类加载器
                    //interfaces - 代理类要实现的接口列表
                    //h - 指派方法调用的调用处理程序 (指定调运那个类的invoke方法)
                    return Proxy.newProxyInstance(this.targetObject.getClass()
                            .getClassLoader(),
                            this.targetObject.getClass().getInterfaces(), this);
                    //参数是this,就表示调运自己的invoke的方法。
                }
                /*
                 * 当代理对象的方法被调运时,就会执行回调函数invoke方法,让这个回调函数再去执行目标代码的指定方法,
                 * 并且会将代理对象接收到的参数传递给目标代码。这是一个回调函数。
                 * 注意:method args 都是由调运代理对象后产生的。所以是确定的。
                 * 还可以在这个回调函数中做一些手脚,比如限制调运或者其他。
                 */
                @Override
                public Object invoke(Object proxy, Method method, Object[] args)
                        throws Throwable {
                    PersonServiceImpl bean = (PersonServiceImpl) this.targetObject;
                    Object result = null;
                    if (bean.getUser() != null) {
                        result = method.invoke(targetObject, args);
                    }
                        return result;
                }
            }
            注意:目标对象必须实现接口。因为需要得到接口的所有方法,然后进行调运接口的所有方法。
        方式2:使用cglib提供的代理对象(代理对象需要实现MethodInterceptor接口,目标对象不需要实现接口)
            //导包:cglib-nodep-2.2.3.jar
            public class CGlibProxyFactory implements MethodInterceptor {
                private Object targetObject;
                /**
                 * 注意,生成的代理对象其实就是目标对象的子类。
                 * @param targetObject
                 * @return
                 */
                public Object createProxyInstance(Object targetObject) {
                    this.targetObject = targetObject;
                    Enhancer enhancer = new Enhancer();// 用于生成代理对象
                    enhancer.setSuperclass(this.targetObject.getClass());// 设置代理对象的父类
                    enhancer.setCallback(this);// 设置回调函数对象为本生
                    return enhancer.create();// 生成代理对象
                }

                /**
                 * 回调函数
                 */
                @Override
                public Object intercept(Object proxy, Method method, Object[] args,
                        MethodProxy methodProxy) throws Throwable {
                    PersonServiceImpl bean = (PersonServiceImpl) this.targetObject;
                    Object result = null;
                    if (bean.getUser() != null) {
                        return result = methodProxy.invoke(bean, args);
                    }
                    return null;
                }

            }
            注意:目标对象不须实现接口。因为生成的代理对象时目标对象的子类。
    使用spring框架中的AOP(使用注解的方法)
        step1.修改配置文件
            加入新的命名空间:xmlns:aop="http://www.springframework.org/schema/aop"
            加入新的约束文件:http://www.springframework.org/schema/aop
                              http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
            加入注册处理器配置:<aop:aspectj-autoproxy/>
            完整的配置文件:
                <?xml version="1.0" encoding="UTF-8"?>
                <beans xmlns="http://www.springframework.org/schema/beans"
                       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                       xmlns:context="http://www.springframework.org/schema/context"
                       xmlns:aop="http://www.springframework.org/schema/aop"     
                       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context-2.5.xsd
                           http://www.springframework.org/schema/aop
                           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
                    <aop:aspectj-autoproxy/>
                </beans>
        step2.导入jar文件
            aspectjrt.jar   aspectjweaver.jar  cglib-nodep-2.2.3.jar
        step3.开发AOP(xml)
            配置aop;
                <bean id="interceptorXML" class="com.spring.aop.InterceptorXML" />
                <bean id="personServiceImpl" class="com.spring.service.impl.PersonServiceImpl"></bean>
                <aop:config>
                    <aop:aspect id="asp" ref="interceptorXML">
                        <aop:pointcut id="aspcut"
                            expression="execution(* com.spring.service.impl.PersonServiceImpl.*(..))" />
                        <aop:before method="before" pointcut-ref="aspcut" />
                        <aop:after method="after" pointcut-ref="aspcut" />
                        <aop:after-returning method="afterReturning"
                            pointcut-ref="aspcut" />
                        <aop:after-throwing method="afterThrowing"
                            pointcut-ref="aspcut" />
                        <aop:around method="around" pointcut-ref="aspcut" />
                    </aop:aspect>
                </aop:config>
            拦截器代码:
                public class InterceptorXML {
                    public void before(){
                        System.out.println("前置通知");
                    }
                    public void afterReturning(){
                        System.out.println("后置通知");
                    }
                    public void afterThrowing(){
                        System.out.println("例外通知");
                    }
                    public void after(){
                        System.out.println("最终通知");
                    }
                    public Object around(ProceedingJoinPoint pjp) throws Throwable{
                        System.out.println("环绕通知");
                        Object result = pjp.proceed();
                        return result;
                    }
                }
        step3.开发AOP(annotation)
            配置aop:
                <aop:aspectj-autoproxy />
                <bean id="interceptorAnnotation" class="com.spring.aop.InterceptorAnnotation"></bean>
                <bean id="personServiceImpl" class="com.spring.service.impl.PersonServiceImpl"></bean>
            拦截器代码:
                @Aspect
                public class InterceptorAnnotation {
                    @Pointcut("execution (* com.spring.service.impl.PersonServiceImpl.*(..))")
                    private void anyMethod(){}//声明一个切入点
                   
                    @Before("anyMenthod()")
                    public void before(){
                        System.out.println("前置通知");
                    }
                    @AfterReturning(pointcut="anyMenthod()")
                    public void afterReturning(){
                        System.out.println("后置通知");
                    }
                    @AfterThrowing(pointcut="anyMenthod()")
                    public void afterThrowing(){
                        System.out.println("例外通知");
                    }
                    @After("anyMenthod()")
                    public void after(){
                        System.out.println("最终通知");
                    }
                    @Around("anyMenthod()")
                    public Object around(ProceedingJoinPoint pjp) throws Throwable{
                        System.out.println("环绕通知");
                        Object result = pjp.proceed();
                        return result;
                    }
                }

猜你喜欢

转载自dyygusi.iteye.com/blog/2048176