Spring学习
Spring简介
Spring四个方面的功能:
- Ioc/DI
- AOP
- 事务
- JdbcTemplate
Spring:解决企业级应用开发的复杂性而创造的。服务端的开发,测试性,松耦合
Spring下载
maven
Ioc
Ioc概念
控制反转,对一个对象的控制权的反转
将对象的创建、初始化、销毁交给容器管理,Bean注册到Spring容器中,使用时。其他对象需要使用Bean是,直接去Spring容器中要
进行bean注入,使用反射方法创建对象
Bean的获取
xml中定义bean
ClassPathXmlApplicationContext
FileSystemXmlApplicationContext
属性注入
构造方法注入
<bean class="org.javagirl.ioc.model.User" id="user">
<!-- 查找构造方法-->
<constructor-arg value="1" name="id"/>
<constructor-arg value="2" name="username"/>
<constructor-arg value="3" name="address"/>
</bean>
set方法注入
<bean class="org.javagirl.ioc.model.User" id="user2">
<property name="id" value="2"></property>
<property name="username" value="2"></property>
<property name="address" value="2"></property>
</bean>
p名称空间注入
<bean class="org.javagirl.ioc.model.User" id="user3" p:username="javagirl" p:id="3" p:address="java.com">
</bean>
工厂方法容器注入
静态工厂注入
实例工厂注入:获取两个实例,更加具体
复杂属性注入
对象注入
<bean class="org.javagirl.ioc.model.User" id="user4">
<property name="id" value="2"></property>
<property name="username" value="2"></property>
<property name="address" value="2"></property>
<property name="cat" ref="cat"></property>
</bean>
<bean id="cat" class="org.javagirl.ioc.model.Cat">
<property name="name" value="xiaoxiao">
</property>
<property name="age" value="4"></property>
</bean>
数组注入
<bean class="org.javagirl.ioc.model.User" id="user4">
<property name="id" value="2"></property>
<property name="username" value="2"></property>
<property name="address" value="2"></property>
<property name="cat" ref="cat"></property>
<property name="cats">
<array>
<ref bean="cat"/>
<bean class="org.javagirl.ioc.model.Cat" id="cat2">
<property name="name" value="xiaoxiao"></property>
<property name="age" value="4"></property>
</bean>
</array>
</property>
<property name="favorites">
<list>
<value>说的话</value>
<value>比如</value>
</list>
</property>
</bean>
<bean id="cat" class="org.javagirl.ioc.model.Cat">
<property name="name" value="xiaoxiao"></property>
<property name="age" value="4"></property>
</bean>
map注入
properties注入
<bean class="org.javagirl.ioc.model.User" id="user4">
<property name="id" value="2"></property>
<property name="username" value="2"></property>
<property name="address" value="2"></property>
<property name="cat" ref="cat"></property>
<property name="cats">
<array>
<ref bean="cat"/>
<bean class="org.javagirl.ioc.model.Cat" id="cat2">
<property name="name" value="xiaoxiao"></property>
<property name="age" value="4"></property>
</bean>
</array>
</property>
<property name="favorites">
<list>
<value>说的话</value>
<value>比如</value>
</list>
</property>
<property name="details">
<map>
<entry key="gender" value="女"></entry>
<entry value="232" key="age"></entry>
</map>
</property>
<property name="info">
<props>
<prop key="phone">132333</prop>
</props>
</property>
</bean>
<bean id="cat" class="org.javagirl.ioc.model.Cat">
<property name="name" value="xiaoxiao"></property>
<property name="age" value="4"></property>
</bean>
java配置
- xml注入
- java配置(java代码将bean注册到容器中)
- 自动化扫描
springboot中使用java配置开发,不使用xml配置
//表示这是一个java配置类,类似于applicationContext.xml
@Configuration
public class JavaConfig {
@Bean
SayHello sayHello(){
return new SayHello();
}
}
public class JavaConfigTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(JavaConfig.class);
SayHello sayHello = ctx.getBean("sayHello", SayHello.class);
System.out.println(sayHello.sayHello("javagirl"));
}
}
自动化配置
包扫描
准备
@Service作为一个标记
@Component 其它组件
@Controller
@Repository Dao层
java代码配置自动扫描
-
定义Service @Service
-
Config配置文件中定义包扫描
@Configuration @ComponentScan(basePackages = "org.javagirl.ioc.service")
-
获取对象并测试
Bean的名字是类名首字母小写,自定义在@service(“名字”)
扫描按照包的位置扫描可以定义过滤字段
xml配置自动化扫描
-
定义Service
-
xml文件中定义component-scan
对象注入
-
@Autowired
根据类型去查找,然后赋值,这个类型只可以有一个对象,否则就会报错
dao文件
@Repository public class UserDao { public String hello(){ return "hello"; } }
@Service public class UserService { @Autowired UserDao userDao;
-
@Resources
根据名称去查找,默认情况下,定义的变量名就是查找的名称。如果一个类存在多个实例,使用该注入方式进行注入。@Autowired需要和@Qualifier(指定变量名)配合使用
-
@Injected
较少使用
条件注解
满足在某一个条件的情况下,生效的配置
条件注解
@Conditional()
多环境切换
开发,生产,测试环境
Profile,底层为条件注解
@Profile
Main:
ctx.getEnvironment().setActiveProfiles("dev");
@Bean
@Profile("dev")
DataSource devDs(){
DataSource ds = new DataSource();
ds.setUrl("jdbc:mysql:///vhr");
ds.setPassword("root");
ds.setUsername("root");
return ds;
}
@Profile("pro")
@Bean
DataSource proDs(){
DataSource ds = new DataSource();
ds.setUrl("jdbc:mysql://172.0.0.1:3307/vhr");
ds.setPassword("root");
ds.setUsername("root");
return ds;
}
xml配置
定义beans,进行配置
其它
Bean的作用域
singleton 默认从spring容器中多次获取的是同一个Bean,单例
scope=“protype” 表示获取多个实例
id和name的区别
id和name都可以给Bean指定一个唯一标识符
name支持取多个名字
混合配置
Java配置+XML配置
在Java配置中引入XML配置
@ImportResource("classpath:applicationContext.xml")
Aware接口
感知捕获,单纯的一个Bean是没有感知
Aware接口可以获取容器的详细信息
@Service
@PropertySource(value="javagirl.properties")
public class AwareService implements BeanNameAware, BeanFactoryAware, ResourceLoaderAware, EnvironmentAware {
private String beanName;
private Environment environment;
private ResourceLoader resourceLoader;
/**
* 获取工厂环境
* @param environment
*/
@Override
public void setEnvironment(Environment environment) {
this.environment=environment;
}
public void output() throws IOException {
System.out.println("beanName = " + beanName);
Resource resource = resourceLoader.getResource("javagirl.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(resource.getInputStream()));
String s = br.readLine();
System.out.println("s = " + s);
br.close();
String address = environment.getProperty("javagirl.address");
System.out.println("address = " + address);
}
/**
* 获取bean的生成工厂
* @param beanFactory
* @throws BeansException
*/
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
}
/**
* 获取bean的名字
* @param s
*/
@Override
public void setBeanName(String s) {
this.beanName=s;
}
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader=resourceLoader;
}
}
Aop
Aop,面向切面编程,对面向对象思想的补充
在不改变源码的情况下,动态的增强方法的功能
日志,事务,数据库操作等
- 切点:添加代码的地方
- 通知(增强):想切点动态添加的代码
- 切面:切面+通知
- 连接点:切点的定义
Aop的实现
基于Java动态代理的实现
实现:
- cglib
- jdk
动态代理
方法增强
public class CalculatorProxy {
public static Object getInstance(MyCalculatorImpl myCalculator){
return Proxy.newProxyInstance(CalculatorProxy.class.getClassLoader(), myCalculator.getClass().getInterfaces(), new InvocationHandler() {
/**
*
* @param proxy 代理对象
* @param method 代理方法
* @param args 方法参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method.getName()+":方法开始执行");
Object invoke = method.invoke(myCalculator, args);
System.out.println(method.getName()+":方法执行结束");
return invoke;
}
});
}
}
五种通知
- 前置通知
@Component
@Aspect
public class LogAspect {
/**
* 前置通知
* @param joinPoint
*/
@Before("@annotation(Action)")
public void before(JoinPoint joinPoint){
String name = joinPoint.getSignature().getName();
System.out.println("add方法开始执行了");
}
}
- 后置通知
/**
* 后置通知,在目标方法之后执行
* @param joinPoint
*/
@After("@annotation(Action)")
public void after(JoinPoint joinPoint){
String name = joinPoint.getSignature().getName();
System.out.println(name+"方法执行结束了");
}
- 异常通知
/**
* 异常通知:当目标方法抛出宜昌市,该方法会被触发
* @param joinPoint
* @param e 异常参数,和方法参数名一一对应,注意异常类型,Exception
*/
@AfterThrowing(value= "@annotation(Action)",throwing = "e")
public void afterThrowing(JoinPoint joinPoint,Exception e){
String name = joinPoint.getSignature().getName();
System.out.println(name+"方法异常通知"+e.getMessage());
}
- 返回通知
/**
* 返回通知,参数类型匹配时有返回通知,Object可以匹配所有类型
* @param joinPoint
* @param r 返回的参数名称,和方法的参数名一一对应
*/
@AfterReturning(value = "@annotation(Action)",returning = "r")
public void returning(JoinPoint joinPoint,Object r){
String name = joinPoint.getSignature().getName();
System.out.println(name+"方法返回通知"+r);
}
- 环绕通知
@Around("@annotation(Action)")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
//类似于method.invoke方法,可以在这个方法的前后分别添加日志,相当于前置/后置通知
Object proceed = pjp.proceed();
return proceed;
}
通过方法定义切点
@Pointcut("@annotation(Action)")
public void pointcut(){
}
另一种方法
@Pointcut("execution(* aop.service.*.*(..))")
public void pointcut(){
}
xml配置aop
JdbcTemplate
JdbcTemplate时Spring利用Aop思想封装的Jdbc操作工具
配置jdbc
java配置
xml配置
事务
利用Aop思想,简化事务的配置,可以通过java配置也可以通过XML配置
XML配置
- 配置事务管理器
- 配置事务处理的方法
- 配置aop
java代码
@Transactional 注解