维基百科的说法:软件框架通常是指为了实现某个业界标准或完成特定基本任务的软件组件规范,也指为了实现某个软件组件规范时,提供规范所要求之基础功能的软件产品。
框架的功能类似于基础设施,与具体的软件应用无关,但是提供并实现最为基础的软件架构和体系。软件开发者通常依据特定的框架实现更为复杂的商业运用和业务逻辑。这样的软件应用可以在支持同一种框架的软件系统中运行。
简而言之,框架就是制定一套规范或者规则(思想),大家(程序员)在该规范或者规则(思想)下工作。或者说使用别人搭好的舞台来做编剧和表演。
总结:框架是带有约束性语法,并且支撑着整个项目的半成品项目。
IOC(反转控制):这是面向对象编程的一种设计原则,可以用来减低代码之间的耦合度。
DI(依赖注入):最常见的方式 DI , 通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体,将所依赖的对象的引用传递(注入)给它。
DL(依赖查找):这是另一种 IOC 的方式。(这里不加以描述)
总结:IOC是一种思想,DI 是一种实现方式。
Q:哪些方面被反转了?
A:对象的获得被反转了。对象交由 spring容器进行管理,避免了对象的获取过程靠自身实现,降低了代码的耦合并且方便了程序的维护与调试。
实现方式如下:
2、基于 set 方法的代码实现
准备工作:一个Person类,编写 get , set 方法
spring 的配置文件 applicationContest.xml 如下
Tips:
1)、当 Person 类的属性存在对象时,使用 ref 进行赋值。
2)、集合类型的赋值方式( util 命名空间)
<bean id="person" class="com.atguigu.spring.mod.Person">
<property name="id" value="1001"/>
<property name="name" value="张三"/>
<property name="home" ref="home"/>
<property name="lt">
<list>
<value>1</value>
<value>2</value>
<value>3</value>
</list>
</property>
</bean>
<bean id="home" class="com.atguigu.spring.mod.Home">
<property name="province" value="广东"/>
<property name="country" value="广州"/>
</bean>
测试(只写一遍,之后的测试都按这样的方式创建 Bean, 因为在实际的开发中,是不需要自己创建的)
public static void main(String[] args) {
ApplicationContext ac= new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = ac.getBean("person", Person.class);
System.out.println(person);
}
3、基于构造函数的代码实现
spring 配置文件如下:
构造函数的方式可以通过 index 、 type 等等方式指定所需要赋值的属性。
<bean id="person2" class="com.atguigu.spring.mod.Person">
<constructor-arg name="id" value="1002" index="0" type="java.lang.Integer"/>
<constructor-arg name="name" value="李四"/>
<constructor-arg name="home" ref="home"/>
</bean>
4、基于Java注解功能:
1、xml 对组件的扫描
<!-- 扫描-->
<context:component-scan base-package="com.atguigu" use-default-filters="true">
<!-- 排除(filters为true) 通过类型 <context:exclude-filter type="assignable" expression="com.atguigu.service.serviceimpl"/>-->
<!-- 包含(filters为false)通过注解 <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>-->
</context:component-scan>
2、注解(类名都用小写了,不规范的)
2-1 Controller
@Controller
public class controller {
@Autowired
service s ;
public void add(){
s.add();
}
public controller(){
System.out.println("Controller");
}
}
2-2 Service
@Service
public class serviceimpl implements service {
public serviceimpl(){
System.out.println("Service");
}
@Autowired
private dao d;
@Override
public void add() {
d.add();
}
}
2-3 Dao
3、测试
public class Test {
public static void main(String[] args) {
ApplicationContext ac=new ClassPathXmlApplicationContext("autowired.xml");
controller c = ac.getBean("controller", controller.class);
System.out.println(c);
c.add();
}
}
@Repository
public class daoimpl implements dao {
public daoimpl(){
System.out.println("Dao");
}
@Override
public void add() {
System.out.println("add");
}
}
----------------------------------其他--------------------------------------------------
BeanFactory;
1、factory:
package com.atguigu.spring.factorybean;
import org.springframework.beans.factory.FactoryBean;
public class MyFactory implements FactoryBean<Car> {
@Override
public Car getObject() throws Exception {
Car car = new Car();
car.setBrand("奥迪");
car.setPrice(1000000);
return car;
}
@Override
public Class<?> getObjectType() {
return Car.class;
}
@Override
public boolean isSingleton() {
return false;
}
}
2、xml
<bean id="factory" class="com.atguigu.spring.factorybean.MyFactory"></bean>
3、测试(略)
Bean 的作用域:
scope=singleton:单例,在xml文件加载时就已经创建好对象,每个对象都一样。
scope=prototype:多例,在 getBean 的时候创建对象,每个对象都不一样。(地址空间不一样)
Bean 的生命周期:
1)创建对象
2)依赖注入
3)初始化 (需在 xml 配置)
4)使用
5)销毁 (需在 xml 配置)
bean 后置处理器 :
1、创建类 实现 BeanPostProcessor
public class AfterHandler implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
Car car = (Car) bean;
if(car.getBrand().equals("奥迪"))
car.setPrice(200000);
else
car.setPrice(100);
return car;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
2、xml
<bean id="afterhandler" class="com.atguigu.spring.factorybean.AfterHandler"></bean>
<bean id="car" class="com.atguigu.spring.factorybean.Car">
<property name="brand" value="奥迪"/>
</bean>
3、测试(略)
1、类接口与实现类(Math 、 MathImpl)
2、代理类
public class ProxyUtil {
private Object mathimpl; //目标对象
public ProxyUtil(Object mathimpl) {
this.mathimpl = mathimpl;
}
public Object getProxy(){
ClassLoader loader = this.getClass().getClassLoader();//类加载器
Class[] interfaces = mathimpl.getClass().getInterfaces();// 目标对象实现的所有接口的class
return Proxy.newProxyInstance(loader, interfaces, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
MyLogger.before(method.getName(), args);
Object result = method.invoke(mathimpl, args);
MyLogger.after(method.getName(), result);
return result;
}catch (Exception e){
MyLogger.throwing();
e.printStackTrace();
}finally {
System.out.println("哪都有我");
}
return null;
}
});
}
}
3、日记
public class MyLogger {
public static void before(String methodName, Object... args){
System.out.println("method: "+methodName+",arguments: "+args);
}
public static void after(String methodName, Object result){
System.out.println("method: "+methodName+",result: "+result);
}
public static void throwing(){
System.out.println("有异常");
}
}
4、测试
public class Test {
public static void main(String[] args) {
ProxyUtil proxy=new ProxyUtil(new MathImpl());
Math math = (Math) proxy.getProxy();
System.out.println(math.add(1,1));
}
}
AOP (面向切面编程),是对 OOP(面向对象编程) 的一种补充。AOP:横向抽取,OOP:纵向继承。
AOP依赖于动态代理的实现。
旨在将横切关注点(公共功能)与业务主体进行进一步分离,封装成一个切面(一个类),以提高程序代码的模块化程度。
AOP图解:
AOP的实现
1、xml
<!-- 开启aspectJ的自动代理功能-->
<aop:aspectj-autoproxy/>
<context:component-scan base-package="com.atguigu.proxy"></context:component-scan>
2、准备好 MathImpl 类和 Math 接口
并且给实现类加上@Component
3、定义切面类
@Pointcut : 公共切入点表达式
@Pointcut(value = "execution(* com.atguigu.proxy.*.*(..))")//公共切入点表达式
public void aspect(){
}
@Before : 前置通知,作用于方法之前。
// @Before(value = "execution(public int com.atguigu.proxy.MathImpl.add(int,int))") //切入点表达式
@Before(value = "aspect()")
public void beforeAspect(JoinPoint joinPoint){
//连接点
Object[] args = joinPoint.getArgs();//获取方法参数
String methodName = joinPoint.getSignature().getName();//获取方法名
System.out.println("方法之前: methodName :"+methodName+",arguments:"+ Arrays.toString(args));
}
@After : 后置通知,相当于动态代理代码中的 finally 中的通知,无论如何都会执行。
@AfterReturning : 返回通知,作用于方法执行之后,可通过 returning 接受方法返回值的变量名,出现异常不会执行。
@AfterReturning(value = "aspect()",returning = "result")
public void returningAspect(JoinPoint joinPoint, Object result){
.......
}
@AfterThrowing: 异常通知。
@Around : 环绕通知,跟动态代理差不多。
一致性、隔离性、持续性
1、xml
<!-- 引入外部文件-->
<context:property-placeholder location="db.properties"/>
<!-- 配置数据源-->
<!-- <bean id="dataSource" class="DruidDataSource">
<property ...>
</bean>-->
<!-- 通过数据源配置jdbcTemplate-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置事务管理器-->
<bean id="dataSourceTransactionManger" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 引用数据源(driver、url、username、password),引用方式与jdbc一样-->
</bean>
<!-- 开启注解驱动,对事务相关的注解进行扫描,解析含义并执行功能-->
<tx:annotation-driven transaction-manager="dataSourceTransactionManger"/>
2、@Transaction : 注解事务(方法上或类上)
属性:
propagation:事务的传播行为,REQUIRED 和 REQUIRED_NEW
isolation:事务的隔离级别
读未提交:脏读 1
读已提交:不可重复读 2
可重复读:幻读 4
串行化:性能低消耗大 8
timeout:事务的超时操作
readOnly:事务的只读
rollbackFor | noRollbackFor:事务的回滚条件