简单来说,就是处理对象的创建、以及对象的依赖关系! 核心理念: IOC inversion of control 控制反转 / DI dependency injection 依赖注入
spring-beans : ioc 实现,配置文件的访问、创建和管理
spring-core: 核心工具包
spring-context:封装IOC容器,提供扩展功能
SpEL : spring的表达式支持
AOP : 面向切面编程支持
Aspects: 对AspectJ框架的支持
instrumentation: 字节码操作
messaging : 对消息服务的支持
transactions : 事务支持
JDBC : spring对JDBC的封装
ORM : spring对于ORM框架的支持
web : 对于web开发的支持
控制权从调用的类转换到Spring容器,由Spring来实例化对象及依赖注入
创建对象 ;依赖注入 (为属性填入实例);一个类实现FactoryBean接口,实现其方法 配置之后,bean的实例为FactoryBean#getObject方法的返回值 java类:
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"/>setter注入:
<bean id="userService" class="com.woniuxy.spring.service.serviceimp.UserServiceImp"> <property name="userDao" ref="userDao"/> </bean> public class UserServiceImp implements UserService { //属性 private UserDaoImp tdi; //setter注入 public void setTdi(UserDaoImp tdi) { this.tdi = tdi; } }构造器注入:
<bean id="userDao" class="com.woniuxy.spring.dao.daoimp.UserDaoImp"/> <bean id="userService" class="com.woniuxy.spring.service.serviceimp.UserServiceImp"> <constructor-arg name="tdi" ref="userDao"/> <constructor-arg index="1" value="20"/> </bean> public class UserServiceImp implements UserService { //属性 private UserDaoImp tdi; private String age; //构造器注入 public UserServiceImp(UserDaoImp tdi,String age){ this.tdi = tdi; this.age = age; } }prototype 原型 => 每次创建一个实例 [*]singleton 单例 => 一个bean的定义,只有一个实例,不是一个类只有一个实例(默认为单例) request 一个请求一个实例 session 一个会话一个实例 websocket 一次websocket链接一个实例
1.在bean配置上写init-method和destroy-method 2.实现InitializingBean和DisposableBean及其方法
public class Cycle2 implements InitializingBean, DisposableBean { @Override public void afterPropertiesSet() throws Exception { System.out.println("开始...."); } @Override public void destroy() throws Exception { System.out.println("结束了...."); } }解耦合,类与类之间的耦合度降低; 提升代码的灵活性,可维护性
注解 注册springbean @Controller @Service @Repository @Component 自动依赖注入 @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>注解: @Bean @Configuration @ComponentScan
@Configuration 标记一个类为配置类 @Bean 标记某个方法返回值为spring的bean,方法参数为依赖注入的请求
扫描
@Configuration 标记一个类为配置类 applicationContext.xml
@ComponentScan 打开包扫描功能,并且指定扫描的包 等价于 <context:component-scan base-package="xxx">
加入@Controller...@Autowired
@PropertySource("{配置文件位置}")
java配置
@Configuration @ComponentScan("com.woniuxy.spring") @PropertySource("database.properties") public class AppConfig { //获取配置文件database.properties里的信息 @Value("${forname}") private String forname; @Value("${url}") private String url; @Value("${user}") private String user; @Value("${password}") private String password; //配置Bean @Bean public UserDaoImp userDaoImp(){ return new UserDaoImp(); } @Bean public UserServiceImp userServiceImp(){ return new UserServiceImp(); } //结束时调用关闭的方法 @Bean(destroyMethod = "close") public DruidDataSource druidDataSource(){ DruidDataSource dds = new DruidDataSource(); dds.setDriverClassName(forname); dds.setUrl(url); dds.setUsername(user); dds.setPassword(password); return dds; } } public static void main(String[] args) throws SQLException { //读取java配置 ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class); //读取Bean,获得实体类 UserServiceImp usi = ac.getBean("userServiceImp",UserServiceImp.class); }AOP Aspect Oritented Programming 面向切面编程 连接点 JoinPoint 需要加入功能的位置,方法 切入点 PointCut 真正执行加入功能的连接点 通知 Advice 需要实现的功能,实现MethodBeforeAdivce接口 前置通知 : 方法执行之前 MethodBeforeAdvice 后置通知 : 方法执行之后 AfterReturningAdvice 环绕通知 : 方法执行前后 MethodInterceptor 异常通知 : 抛出异常时 最终通知 : finally 切面 Aspect Java语言中,将切入点和通知等组装在一起的代码单元 目标对象 Target 要操作的对象 织入 Weave 将功能加入到切入点中的过程 事务 : 一批同时成功或失败的DML
打印日志、性能监控、事务管理、安全验证,每一个类的每一个public方法的参数都打印出来…
1.配置service 2.配置通知 3.配置切入点,class= org.springframework.aop.support.JdkRegexpMethodPointcut 4.配置属性pattern=> service的方法 5.配置切面,class=org.springframework.aop.support.DefaultPointcutAdvisor 连接切入点和通知 6.包装service类, class= org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator 7.获取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.service.serviceimp.UserServiceImp"/> <!--通知: 实现了打日志的功能--> <bean id="beforeExecution" class="com.woniuxy.spring.component.Before"/> <!--切入点:选出了需要增加功能的方法--> <bean id="pointCut" class="org.springframework.aop.support.JdkRegexpMethodPointcut"> <property name="pattern" value="com.woniuxy.spring.service.serviceimp.UserServiceImp.addUser"/> </bean> <!--切面:连接切入点和通知,让打日志功能在切入点的位置执行--> <bean id="aspect" class="org.springframework.aop.support.DefaultPointcutAdvisor"> <property name="pointcut" ref="pointCut"/> <property name="advice" ref="test"/> </bean> <!--包装userService--> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"> <!-- <property name="proxyTargetClass" value="true"/>--> </bean> <bean id="test" class="com.woniuxy.spring.component.Test"/> </beans>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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <!--目标对象--> <bean id="userService" class="com.woniuxy.spring.service.serviceimp.UserServiceImp"/> <!--通知: 实现了打日志的功能--> <bean id="txAdvice" class="com.woniuxy.spring.component.Test1"/> <aop:config> <aop:aspect ref="txAdvice"> <aop:pointcut id="servicePointcut" expression="execution(* com.woniuxy.spring.service.serviceimp.UserServiceImp.*(..))"/> <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> </beans>java注解
@Configuration @ComponentScan("com.woniuxy.spring") @EnableAspectJAutoProxy public class TXconfig { }1.代理类和被代理类必须有相同的接口 2.代理类持有了被代理类对象 一个有趣的代理模式代码: 接口
public interface Invest { double invoke(double money); }Boss类
public class Boss implements Invest{ public double invoke(double money) { System.out.println("老板:"+money+"万,已经打在卡上了,你看到没有"); return money; } }Proxy类
public class Proxy implements Invest{ Boss boss = new Boss(); public Proxy(Boss boss){ this.boss = boss; } public double invoke(double money) { double newMoney = money *1.2; System.out.println("代理:客户需要"+money+"万,我给老板说需要"+newMoney+"万,自己扣下"+(money*0.2)+"万"); double bossMoney = boss.invoke(newMoney); return money; } }Subject类
public class Subject { public static void main(String[] args) { Boss boss = new Boss(); Invest in = new Proxy(boss); System.out.println("客户:我需要1000.0万"); double money = in.invoke(1000); System.out.println("客户:已经收到了"+money+"万"); } }