Spring
优点:
1.方便解耦(降低程序的依赖),简化开发
解耦
耦合:程序间的依赖关系 eg:类之间,方法之间
解耦:降低依赖关系
解耦思路:
1.利用反射来创建对象,避免使用new关键字
2.读取配置文件来获取创建对象的全限定名
2.AOP编程(面向切片编程)
3.方便测试
4.事务支持
5.方便集成框架
6.降低API的使用难度
核心容器:
Beans :产生对象
Core:核心
Context:上下文
SpEL:表达式语言
耦合
ui调用业务层,业务层调用持久层–高度耦合
持久层
业务层
表现层
Spring开发步骤
1.导入Spring的基本包坐标
2.编写dao接口的实现类
3.创建Spring核心配置文件
4.Spring中配置Userdao实现
5.用Spring的api获得对象的实例
Spring IOC加载
1.把 bean的定义信息 scope lazy懒加载 用 BeanDefinition装起来 里面就是 实例信息
然后 通过反射 加载到 bean 工厂
Bean标签
id: xml文件中的编号
class: 接口/对象的位置
init-method方法: init-method=“init”
destory-method方法 : destory-method=“destory”
scope: singleton 只有一个对象 创建xml文件的时候就创建了 /prototype:多个对象 每次调用的时候再创建/request 放入request域/session 放入 sessioin域/global session 不是Portlet,相当于session
默认是无参构造,必须有无参构造
实例化的三种方式
1.无参构造
2.工厂静态方法–直接调用方法
直接在bean里面加入factor method方法
3.工厂实例方法–
1.定义原来类
2.配置xml中bean标签中得到的原类的方法,再通过另一个bean标签配置一个方法得到原类的方法的方法
3.调用Spring方法直接可以用方法
Bean依赖注入
把对象创建交给Spring,框架 把持久层传入业务层
1.构造方法
2.set方法
id :bead的唯一标识 不允许重复
class: bean的全限定名
scope :作用范围
:属性注入
name:属性名称
value:属性值
ref:注入对象的引用值
标签
Spring对应的api
1.传字符串(id)
1.类型找
如果出现某个类型的参数值出现一个,就可以这样找,如果同个类型多个就用id获取
Spring配置数据源–(连接池)
1.数据源开发步骤
1.导入数据源坐标 驱动
在pom.xml文件中创建dependency
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.32</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
2.创建数据源对象
主方法(Spring配置):
1.创建applicationContext.xml文件
2.配置jdbc.properties文件 --设置jdbc健值
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/song
jdbc.username=root
jdbc.password=123456
3.加载外部的properties文件,properties在context标签下,所以先引入context命名空间
<?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 http://www.springframework.org/schema/context/spring-beans.xsd
">
<!-- 加载外部properties文件-->
<context:property-placeholder location="jdbc.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
3.设置基本连接数据
4.拿资源
5.关闭
public static void test4() throws PropertyVetoException, SQLException {
//通过Spring容器产生源对象
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//2.直接通过类型找
DataSource dataSource = applicationContext.getBean(DataSource.class);
Connection connection = dataSource.getConnection();
System.out.println(connection);
connection.close();
}
其他方法
1.c3p0和druid连接池直接写入
public void test1() throws PropertyVetoException, SQLException {
ComboPooledDataSource dataSource=new ComboPooledDataSource();
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/song");
dataSource.setUser("root");
dataSource.setPassword("123456");
Connection connection =dataSource.getConnection();
System.out.println(connection);
connection.close();
}
public static void test2() throws PropertyVetoException, SQLException {
DruidDataSource dataSource=new DruidDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/song");
dataSource.setUsername("root");
dataSource.setPassword("123456");
DruidPooledConnection connection=dataSource.getConnection();
System.out.println(connection);
connection.close();
}
2.调用properties对象
public static void test3() throws PropertyVetoException, SQLException {
//读取配置文件
ResourceBundle rb=ResourceBundle.getBundle("jdbc");
String driver=rb.getString("jdbc.driver");
String url=rb.getString("jdbc.url");
String username=rb.getString("jdbc.username");
String password=rb.getString("jdbc.password");
//连接参数
ComboPooledDataSource dataSource=new ComboPooledDataSource();
dataSource.setDriverClass(driver);
dataSource.setJdbcUrl(url);
dataSource.setUser(username);
dataSource.setPassword(password);
Connection connection =dataSource.getConnection();
System.out.println(connection);
connection.close();
}
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/song
jdbc.username=root
jdbc.password=123456
Spring注解
@Component 用于3层都可以
@Controller用在层
@Service 用在service层
@Repository 用在dao层
@Autowired 按照类型在spring中进行匹配 (必写)
@Qualifier 按照id(名称)进行匹配
@Resoure 根据id找 相当于@Autowired+@Qualifier
注解步骤:
1.在xml文件中写入注解扫描
2.在持久层和业务层的实现类中写相应的注解
4.web层实现
特殊注解
@Value 注入普通属性
@Scope Bean的作用范围 单个还是多个bean
@PostConstruct 之前
@PreDestory 之后
新注解
@Configuration指定他是一个spring配置的类
@ComponentScan指定需要扫描的包
@Bean写在方法上表示放在Spring容器的方法
@PropertySource指定.properties的文件(jdbc)
@Import 导入其他类
将xml配置文件转换为 用注解加载.java文件
1.创建Spring加载文件
2.创建Dadasource加载文件
3.改写web层加载配置
Spring集成Junit
1.导入junit坐标和Spring集成junit坐标
2.用@Runwith注解替换原理运行期间
3.用@ContextConfiguration指定配置文件或者配置类
4.用@Autowired注入测试对象
5.创建方法进行测试
Spring动态代理
特点:字节码随意创建,随时加载
作用:不修改源码的基础对方法进行增强
分类:
- 基于接口的动态代理
- 基于子类的动态代理
基于接口的动态代理
涉及的类:proxy
提供者:JDK官方
如何创建代理对象
用proxy类中的newProxyInstance方法
创建代理对象的要求:
被代理类最少实现一个接口,
newProxyInstance方法
ClassLoader:类加载器 ,加载代理对象字节码,和代理对象有相同的类加载器
(固定的xxx.getClass().getClassLoader())
Class[] : 字节码数组 代理对象和被代理对象有相同的方法
(固定的xxx.getClass().getInterfaces())
InvocationHandler:提供增强代码,一般写一个接口实现类,
基于子类的动态代理
导包:
涉及的类:Enhancer
提供者:第三方cglib库
如何创建代理对象
用Enhancer类中的create方法
创建代理对象的要求:
被代理类不是最终类
creat方法
Class[] : 字节码数组 代理对象和被代理对象有相同的方法
(固定的xxx.getClass().getInterfaces())
Callback :用于提供增强代码,MethodInterceptor()
AOP
AOP:面向切面编程
作用:程序运行时,不修改源码,对已有方法进行增强
优势: 1.减少重复代码 2.提高开发效率 3.维护方便
实现方式:动态代理
JoinPoint连接点: 业务层中所有的方法(增删改查)
Pointout切入点:被增强的方法(事务的开启,执行,提交,返回,回滚)
Advicet(通知):
Target(目标对象):被代理对象
Weaving(织入)
增强应用到代理的过程
proxy(代理对象)
Aspect(切入)
基于xml的AOP配置
1.Bean给spring来管理
2.aop:config标签开始aop配置
3.aop:aspect标签表明配置切面
id:给切面提供一个标志
ref:指定通知类的beanid
4.在aop:aspect标签的内部使用对应标签设置通知类型-
printlog方法在切入点方法执行之前
aop:before前置通知
method:指定logger类中哪个方法的前置通知
pointcut:指定切入点表达式,指定哪些方法增强
切入点表达式的写法
关键字:execution
1.标准表达式写法
public void com.it.service.IAccountServiceimpl.saveAccount()
2.访问修饰符可以省略
void com.it.service.IAccountServiceimpl.saveAccount()
3.返回值可以用通配符,表示任意返回值
com.it.service.IAccountServiceimpl.saveAccount()
4.包名可以用通配符,表示任意包,但是有几级包就要写几个
- ....AccountServiceImpl.saveAccount()
包名可以使用…表示当前包及其子包
类名和方法名走可以用 * 来实现通配
参数列表:
1.直接写数据类型
2. 直接 . .代表有参无参都可以
实际写法 - com.it.service.IAccountServiceimpl.*(. .)
通用写法:
2.全通配写法
- ….*(…)
环绕通知
可以在代码中
问题:切入点方法不执行,通知方法执行了
解决:Spring提供ProceedingJoinPoint,该接口有一个方法 proceed(),调用切入点方法
基于注解的AOP配置
1.改命名空间 改为context以及bean.xml的配置
2.给调用的实体类写上注解
3.写4个通知
4.发现 通知顺序异常 ,处理不了的
5.采用环绕通知 可以避免这个问题
6.纯注解的方式
JdbcTemplate
1.继承JdbcDaoSupport父类
1.xml中set注入jdbcTemplate对象
2..继承JdbcDaoSupport类
3..采用父类的getJdbcTemplate()方法 实现crud...
public class AccountDaoimpl extends JdbcDaoSupport implements IAccountDao {
@Override
public Account FindAccountbyid(int accountid) {
List<Account> accounts = super.getJdbcTemplate().query("select * from account1 where id =?", new BeanPropertyRowMapper<Account>(Account.class), accountid);
return accounts.isEmpty() ? null : accounts.get(0);
}
}
2.直接用JdbcTemplate(需要配置)
1.在bean.xml中配置
2.在持久层的运用(注解)
持久层调用jdbctemplate
@Repository("accountDao")
public class AccountDaoimpl2 implements IAccountDao {
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public Account FindAccountbyid(int accountid) {
List<Account> accounts = jdbcTemplate.query("select * from account1 where id =?"