Spring框架
Spring是一种开源而轻量级的框架,为解决企业应用开发的复杂性而创建的,它一方面为MVC提供工厂模式功能,另一方面可以协同Struts、Hibernate、WebWork、 JSF等众多框架,而其核心容器的主要组件是Bean工厂(BeanFactory)。Bean工厂使用控制反转(IOC)模式来降低程序代码之间的耦合度,并提供了面向切面编程(AOP)的实现。。
IOC
控制反转或称为DI(依赖注入):明确定义组件的接口,独立开发各个组件,然后根据组件的依赖关系组装运行,将创建及管理对象的权利交给Spring容器。
- 配置方式分为分为三类:
a)使用配置文件xml,使用bean标签,根据关系配置,如
<bean id="UserDao" class="com.woniu.dao.daoimp.UserDaoImpl" />
<bean id="UserService" class="com.woniu.service.serviceimp.UserServiceImpl" />
<bean id="WorkService" class="com.woniu.service.serviceimp.WorkServiceImpl">
<property name="userdao" ref="UserDao"/>
</bean>
b)使用注解,又分为两种:
1)使用配置文件(扫描包名)+注解
<context:component-scan base-package="包名" />
@Component : 组件。标识这是个受 spring 管理的组件。
@Controller:用于标注控制层组件
@Service:用于标注业务层组件。
@Repository:用于标注数据访问组件,即DAO组件。
@Scope("prototype") :将Action的范围设置为原型(也就是多例的)。保证每一个请求有一个单独的 Action 来处理。
2)java(扫描包名)+注解
@ComponentScan("com.woniu"):扫描包
其它注解同上
c)Java配置
@Configuration//标注java配置类
public class UserControllerConfig {
private final static UI ui=new UI();
@Bean
public UI ui(){
ui.setMainMenuService(mainMenuService());
return ui;
}
@Bean
public MainMenuService mainMenuService() {
MainMenuServiceImpl mainMenuService =new MainMenuServiceImpl(userDao(),ui);
return mainMenuService;
}
@Bean
public UserDao userDao(){
return new UserDaoImpl(queryRunner());
}
@Bean
public DataSource dataSource(){
DruidDataSource dataSource=new DruidDataSource ();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://...");
dataSource.setUsername("...");
dataSource.setPassword("...");
dataSource.setInitialSize(8);
return dataSource;
}
@Bean
public QueryRunner queryRunner(){
return new QueryRunner(dataSource());
}
}
2.实例化有四种方式
a)默认构造器实例化
<constructor-arg>
<ref bean="">
</constructor-arg>
b)静态工厂实例化
<bean id="" factory-method="" class=".."/>
c)工厂bean实例化
<bean id="holidayFactory" class="...holidayFactory" />
<bean id="holiday" factory-bean="holidayFactory" factory-method="..."/>
d)FactoryBean接口实例化
配置xml中:<bean id="" class=".."/>
Java类中实现FactoryBean接口
public class CarFactory implements FactoryBean<Car>{
public Car getObject() throws Execption{
return new Car();
}
public Class<?> getObjectType(){
return Car.class;
}
}
3.依赖注入有两种方式
a)setter注入:类里面私有属性需要配set方法,配置文件使用
<bean id="" class="...类名">
<property name="属性名" ref="bean对象"/>
</bean>
b)构造器注入:类里面要有相应参数的构造器
<bean id="" class="...类名">
<constructor-arg>
<ref bean="">
</constructor-arg>
</bean>
- Bean的生命周期
5.Bean的作用域【scope】
a)prototype:原型–>每次创建一个实例
b)singleton:单例–>一个bean的定义,只有一个实例,一个类只用一个实例
c)request:一个请求一个实例
d)session:一个会话一个实例
e)websocket:一次websocket链接一个实例
6.IOC的优势及实现
优点:解耦,降低耦合度,提高代码的灵活性和可维护性
实现:xml解析,反射创建实例和递归
AOP
具有横切性质的系统功能,例如:日志记录、性能统计、事务管理、安全检查等等。散布在系统的各个类中。需要一种机制能将这类功能自动加入到需要的位置中去。这种机制就是AOP(面向切面编程)。
1.应用场景
a)Authentication 权限
b)Caching 缓存
c)Context passing 内容传递
d)Error handling 错误处理
e)Lazy loading 懒加载
f)Debugging 调试
g)logging, tracing, profiling and monitoring 记录跟踪 优化 校准
h)Performance optimization 性能优化
i)Persistence 持久化
j)Resource pooling 资源池
k)Synchronization 同步
2.相应名词
- 连接点 joinpoint 需要加入功能的位置(方法)
- 切入点 pointcut 执行加入功能的连接点,从连接点选出的需要加入功能的连接点
- 通知 advice 需要实现的功能
- 切面 aspect 切入点和通知的组合
- 目标对象target 连接点(方法)所在的对象
- 织入 weave 将切面应用到目标对象的过程
3.通知类型 - 前置通知 (Before advice): 方法执行之前 接口:MethodBeforeAdvice
- 后置通知(After returning advice): 方法执行之后 接口: AfterReturningAdvice
- 环绕通知(Around Advice): 方法执行前后 接口:MethodInterceptor
- 异常通知 (After throwing advice): 抛出异常时 接口:ThrowsAdvice
- 最终通知(After (finally) advice) : finally执行时
4.配置方式
a)通过接口:通过实现相应接口,并在xml配置以下代码:
<!--目标对象-->
<bean id="userService" class="com.woniu.build.service.serviceimp.UserServiceImpl"/>
<!--通知:实现了功能-->
<bean id="beforeExecution" class="com.woniu.build.componet.BeforeExecution"/>
<bean id="afterExecution" class="com.woniu.build.componet.AfterExecution"/>
<bean id="interExecution" class="com.woniu.build.componet.InterExecution"/>
<!--切入点:选出需要该功能的对象-->
<bean id="pointCut" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
<property name="patterns" value="com.woniu.build.service.serviceimp.UserServiceImpl.*"/>
</bean>
<!--切面:连接切入点和通知,让该功能在切入点的位置执行-->
<bean id="Aspect" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="pointcut" ref="pointCut"/>
<property name="advice" ref="interExecution"/>
</bean>
<!--包装userService-->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
<property name="proxyTargetClass" value="true"></property>
</bean>
b)通过注解:
前置通知: 注解为 @Before
后置通知: 注解为 @AfterReturning
异常通知: 注解为 @AfterThrowing
环绕通知: 注解为 @Around
最终通知: 注解为 @After
要加上
@Aspect 声明该类是一个通知;
@Component 放入Spring容器中
使用注解进行通知的配置的话,与接口有一点不同,利用注解的话只需要在.xml中开启注解对AOP的支持就行
<context:component-scan base-package="包名"/>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
或通过扫描包,
<context:component-scan base-package="包名"/>
或者写一个Java类扫描
@Configuration
@ComponentScan("包名")
@EnableAspectJAutoProxy
c)通过java配置类
@Component
@Aspect
public class TxtConfig {
@Pointcut(value="execution(* com.woniu.build.service.serviceimp.*.*(..))")
public void servicePointcut(){}
@Around("servicePointcut()")
public Object test(ProceedingJoinPoint point){
Object[] args = point.getArgs();
Object result=null;
try {
System.out.println("开启事务");
result = point.proceed(args);
System.out.println("提交事务");
} catch (Throwable throwable) {
System.out.println("回滚事务");
throwable.printStackTrace();
}
return result;
}
}
d)通过aop标签 (不加注解,不用实现接口)
<!--目标对象-->
<bean id="userService" class="com.woniu.build.service.serviceimp.UserServiceImpl"/>
<!--通知-->
<bean id="transaction" class="通知类方法"/>
<aop:config>
<aop:aspect ref="transaction">
<!-- 切入点-->
<aop:pointcut id="servicepointcut" expression="execution(* com.woniu.build.service.serviceimp.*.*(..))"/>
<!-- 通知-->
<!--前置--> <aop:before method="start" pointcut-ref="servicepointcut"/>
<!--后置--><aop:after-returning method="commit" pointcut-ref="servicepointcut"/>
<!--回滚--><aop:after-throwing method="rollback" pointcut-ref="servicepointcut"/>
</aop:aspect>
</aop:config>