一、spring解决的主要问题

**

  1. 通过依赖注入(DI)方式,在构造方法或者java bean属性上,依赖关系是明确的和明显的。
  2. IoC容器往往是轻量级的,特别是与EJB容器相比。这是有利于在有限的内存和CPU资源的计算机上开发和部署应用程序。
  3. Spring不重新发明轮子,相反,它利用一些现有的技术如几个ORM框架,日志框架,JEE,quartz和JDK计时器,其他视图技术等。
  4. Spring是模块化的。尽管包和类很重要,你只关心你需要的模块,忽略其它模块。
  5. 在Spring测试应用程序很简单,因为依赖环境的代码被移入到框架本身。此外,通过使用JavaBean-style pojo方式,使用依赖注入注入测试数据变得更容易。
  6. Spring的web框架是一个设计良好的web MVC框架,它可以很好的替代其它web框架如struts或者其它web框架。
  7. Spring提供了一致的事务管理界面,可以管理小到一个本地事务(例如,使用一个数据库)和大到全局事务(例如,使用JTA)。

**

二、 IOC

**

概念

**
控制反转,将控制权从调用者转到了spring的IOC容器,由IOC容器进行实例化和依赖注入

**

IOC配置方式

**
1、XML配置式IOC

<?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.xsd">

    <bean id="userDao" class="com.woniuxy.daoimp.UserDaoImp">
        <property name="age" value="18"/>
        <property name="jobs">
            <list>
                <value>doctor</value>
                <value>farmer</value>
                <value>driver</value>
            </list>
        </property>
        <property name="data">
            <map>
                <entry key="1" value="q"/>
                <entry key="2" value="w"/>
                <entry key="3" value="e"/>
            </map>
        </property>
        <property name="hometv">
            <set>
                <value>电视</value>
                <value>冰箱</value>
                <value>洗衣机</value>
            </set>
        </property>
    </bean>
    <bean id="userDao2" class="com.woniuxy.daoimp.UserDaoImp"/>
    <bean id="suerService" class="com.woniuxy.serviceimp.UserServiceImp">
        <property name="userDao" ref="userDao"/>
        <property name="userDaoList">
            <list>
                <ref bean="userDao"/>
                <ref bean="userDao2"/>
            </list>
        </property>
    </bean>

    <bean id="userController" class="com.woniuxy.controller.UserController">
        <property name="userService" ref="suerService"/>
    </bean>

    <!--用一个静态工厂创建一个connetion作为一个springbean-->
    <bean id="connection" factory-method="getConnection" class="com.woniuxy.utils.JDBCUtils"/>

    <bean id="holidayFactory" class="com.woniuxy.factory.HolidayFactory"/>
    <bean id="holiday" factory-method="create" factory-bean="holidayFactory"/>


    <bean id="car" class="com.woniuxy.factory.CarFactory"/>

</beans>

2、注解式的配置IOC

  • 注册springbean @Controller(标记控制层) @Service (标记service层) @Repository(标记dao 层) @Controller(标记前面三种以为其他的)
  • 自动依赖注入 @Autowired (自动注入的属性) @Value
  • 生命周期 @PostConstruct(初始化) @PreDestroy(销毁)
  • 作用域范围 @Scope
  • 注解式还需要配置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"
         xmlns:context="http://www.springframework.org/schema/context"
         xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
  
      <!--指定扫描的范围,包括递归的所有的包和子类-->
      <context:component-scan base-package="com.woniuxy.spring"/>
  
  </beans>

3、纯java 配置式的IOC

@Configuration  标记一个类为配置类    applicationContext.xml

@ComponentScan   打开包扫描功能,并且指定扫描的包  等<context:component-scan  base-package="xxx">
@Controller
@Autowired 
@Service
@Repository...
@PropertySource("{配置文件位置}")

4、混合使用配置式配置IOC

在注解类上可以用@Import导入Java配置,用ImportResource导入xml配置
@Import(AppConfig.class)
@ImportResource("applicationContext.xml")

**

实例化的几种方式

**
1、默认构造器实例化

<bean id="carFactory" class="xxxx.CarFactoryBean"/>

2、静态工厂实例化

<bean id="connection" factory-method="getConnection" class="com.woniuxy.spring.common.JDBCUtils"/>

3、实例工厂实例化

<bean id="holidayFactory" class="com.woniuxy.spring.factory.HolidayFactory"/>
<bean id="holiday" factory-bean="holidayFactory" factory-method="create"></bean>

4、Spring的FactoryBean接口实例化,实现接口, 重写getObject和getObjectType

public class CarFactory implements FactoryBean<Car> {
       
           @Override
           public Car getObject() throws Exception {
               return new Car();
           }
       
           @Override
           public Class<?> getObjectType() {
               return Car.class;
           }
       }
       
xml配置:
<bean id="car" class="com.woniuxy.spring.factory.CarFactory"/>

**

依赖注入的几种方式

**
1、setter注入
必须提供setter方法
2、构造器注入
有参构造 (constructor-arg name=“参数名字” index=“参数序号” value=“参数值” ref=“引用的bean” )
3、接口注入

**

bean的生命周期、作用域

**
Spring框架提供了以下四种方法控制bean的生命周期事件:

InitializingBean和DisposableBean回调接口
其他知道接口为特定的行为
定制的init()和destroy()方法在bean配置文件
@PostConstruct和@PreDestroy注解

spring容器中的bean有5中scope,分别是:

单例singleton:默认情况下都是单例的,它要求在每个spring 容器内不论你请求多少次这个实例,都只有一个实例。单例特性是由beanfactory本身维护的。
原型prototype:这个bean的实例和单例相反,一个新的请求产生一个新的bean实例。
请求request:在一个请求内,将会为每个web请求的客户端创建一个新的bean实例。一旦请求完成后,bean将失效,然后被垃圾收集器回收掉。
会话session:就像请求范围,这样可以确保每个用户会话bean的一个实例。当用户结束其会话,bean失效。
全局会话global-session:应用到Portlet应用程序。基于Servlet的应用程序和会话相同。

IOC的优势

  • 解耦合,类与类之间的耦合度降低; 提升代码的灵活性,可维护性

三、AOP的概念、应用场景及配置方式

AOP概念

具有横切性质的系统功能,例如:日志记录、性能统计、事务管理、安全检查等等。散布在系统的各个类中。需要一种机制能将这类功能自动加入到需要的位置中去。这种机制就是AOP。

AOP名词

  • 连接点 joinpoint 需要加入功能的位置(方法)
  • 切入点 pointcut 执行加入功能的连接点,从连接点选出的需要加入功能的连接
  • 通知 advice 需要实现的功能
  • 切面 aspect 切入点和通知的组合
  • 目标对象 target 连接点(方法)所在的对象
  • 织入 weave 将切面应用到目标对象的过程

AOP通知类型

  • 前置通知 : 方法执行之前 实现MethodBeforeAdvice接口
  • 后置通知 : 方法执行之后 实现AfterReturningAdvice接口
  • 环绕通知 : 方法执行前后 实现MethodInterceptor接口
  • 异常通知 : 抛出异常时
  • 最终通知 : finally执行时

AOP应用场景

Authentication 权限
Caching 缓存
Context passing 内容传递
Error handling 错误处理
Lazy loading 懒加载
Debugging  调试
logging, tracing, profiling and monitoring 记录跟踪 优化 校准
Performance optimization 性能优化
Persistence  持久化
Resource pooling 资源池
Synchronization 同步
Transactions 事务
日志记录、性能统计、事务管理、安全检查等等

AOP配置方式

1、XML配置方式

  • 配置service
  • 配置通知
  • 配置切入点,class=org.springframework.aop.support.JdkRegexpMethodPointcut,配置属性pattern=> service的方法
  • 配置切面,class=org.springframework.aop.support.DefaultPointcutAdvisor 连接切入点和通知
  • 包装service类, class=org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator
  • 获取bean,调用方法,将会看到通知执行了
<?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.xsd">
    <!--目标对象-->
    <bean id="userService" class="com.woniuxy.spring.aop.service.impl.UserServiceImpl"/>
    <!--通知: 实现了打日志的功能-->
    <bean id="beforeExecution" class="com.woniuxy.spring.aop.component.BeforeExecution"/>

    <!--切入点:选出了需要增加功能的方法-->
    <bean id="pointCut" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
        <property name="pattern" value="com.woniuxy.spring.aop.service.impl.UserServiceImpl.addUser"/>
    </bean>

    <!--切面:连接切入点和通知,让打日志功能在切入点的位置执行-->
    <bean id="aspect" class="org.springframework.aop.support.DefaultPointcutAdvisor">
        <property name="pointcut" ref="pointCut"/>
        <property name="advice" ref="beforeExecution"/>
    </bean>

    <!--包装userService-->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>


</beans>

另外一种配置切面的方式:

<!--切面配置-->
    <aop:config>
        <aop:aspect ref="txAdvice">
            <!--切入点-->
            <aop:pointcut id="servicePointcut" expression="execution(* com.woniuxy.spring.aop.service.impl.*.*(..))"/>
            <!--通知-->
            <!--前置--><aop:before method="begin" pointcut-ref="servicePointcut"/>
            <!--后置--><aop:after-returning method="commit" pointcut-ref="servicePointcut"/>
            <!--异常--><aop:after-throwing method="rollback" pointcut-ref="servicePointcut"/>
        </aop:aspect>
    </aop:config>


<第一个*代表方法返回值,第二个*代表某个包下面的所有类,第三个*代表类下面的所有方法,(..)代表方法的任意参数>
execution(* com.woniuxy.spring.aop.service.impl.*.*(..))

execution(void com.woniuxy.spring.aop.service.ProductService.addProduct())

execution(User com.woniuxy.spring.aop.service.UserService.addUser(User))

2、注解式配置

@Aspect (标记一个类为切面)
@Pointcut(切入点)
@Around (环绕通知)
@Before(前置通知)
@After (后置通知)
@AfterReturning (最终通知)
@AfterThrowing(异常通知)
@EnableAspectJAutoProxy(表示开启AOP代理自动配置)