Spring
# Spring
# IOC
Inversion of control / Dependency injection
IOC容器创建,并通过bean工厂获取类对象(仅当接口的实现类唯一,可以根据接口获取bean)
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml"); User user = (User) ioc.getBean("user"); User user = (User) ioc.getBean(User.class); User user=(User) ioc.getBean(UserService.class);1
2
3
4①实例化方法默认调用无参构造器。同时通过setter依赖注入(简单类型ioc是通过get和set方法对属性进行赋值,引用类型使用ref标签引用其它bean的id)
<bean id="school" class="pojo.School"> --通过无参构造方法实例化Bean <bean id="stu" class="pojo.Stu"> <property name="name" value="村姑"></property> <property name="age" value="20"></property> <property name="address"> <null></null> </property> <property name="school" ref="school"/> </bean>1
2
3
4
5
6
7
8
9
10②通过实现一个工厂类FactoryBean来实例化Bean(注意这里bean的class配置的是工厂类)
public class UserDaoFactoryBean implements FactoryBean<UserDao> { @Override public UserDao getObject() throws Exception { return new UserDaoImpl(); } @Override public Class<?> getObjectType() { return UserDao.class; } } ----配置----- <bean id="userDao" class=factory.UserDaoFactoryBean/>1
2
3
4
5
6
7
8
9
10
11
12构造器注入使用constructor-arg
导入第三方Bean,并导入资源文件
<context:property-placeholder location="jdbc.properties"/> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${driver}"></property> <property name="url" value="${url}"></property> <property name="username" value="${username}"></property> <property name="password" value="${password}"></property> </bean>1
2
3
4
5
6
7自动装配:ioc容器根据bean依赖的资源或属性在容器中自动查找并注入到bean的属性的过程。
方法①使用ref标签。方法②通过给bean指定autowire="byType",bean下所有的依赖根据属性类型去bean里面找匹配的类型来实例化(不能用于简单类型)。注意这两种方法依赖属性都需要实现set方法
加载properties/生命周期/...
# 注解开发
定义bean通过给类添加注解@Componet(@Controller,@Service,@Repository),还可以给某个方法添加@Bean,表示方法的返回对象添加到ioc容器中(根据方法名创建bean)。
在applicationContext.xml中只添加如下,表示扫描包下所有的类的注解标签
<context:component-scan base-package="Dao,aop"> ----spring扫描其它组件,springMVC扫描控制层,使用排除扫描---- <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan>1
2
3
4
5纯注解开发
----定义配置类---- @Configuration @ComponentScan({"包1","包2"}) public class SpringConfig{ } ----使用--- ApplicationContext ioc=new AnnotationConfigApplicationContext(SpringConfig.class); ioc.getBean("") ----其它注解类型----- @autowired 引用类型自动装配,不需要实现set方法 @value("admin") 普通类型自动装配 @Bean 当前方法返回的是一个bean,通过getBean获取 第三方Bean注入资源直接在方法形参写上资源类型,Spring自动会根据类型注入资源1
2
3
4
5
6
7
8
9
10
11
12
13
# AOP
通过代理对象控制核心方法抽离
静态代理:A和B类共同实现了C接口,A类中如果要给核心方法增强功能,比如在前后添加日志,或者是try-catch捕获异常,那么开发者在实现A类中就不能够只专注于业务。所以做法是实现B类,类里面有一个A的实例对象,重写C类接口方法的同时再调用A把核心方法放进去,前后进行增强实现。这样子既能做到通过A修改核心方法,同时也能够增强实现方法。
B{ fun{ 日志1; A.fun(); 日志2; }}1
2
3
4
5
6动态代理: 动态生成一个代理对象,可以代理任意类(target)和接口。通过反射调用目标类的接口方法。
jdk动态代理要求必须要有接口,生成的代理类和目标类不在同一个包下。
cglib最终代理类会自动继承目标类。
public Object getProxy() { ClassLoader classLoader = target.getClass().getClassLoader(); Class<?>[] interfaces = target.getClass().getInterfaces(); InvocationHandler h=new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //... Object result = method.invoke(target, args); //... return result; } }; return Proxy.newProxyInstance(classLoader, interfaces, h); }1
2
3
4
5
6
7
8
9
10
11
12
13
14AOP相关术语
横切关注点:非核心业务方法
切面:把所有横切关注点放到切面类中进行封装,每个横切关注点都叫做一个通知。
连接点:原目标方法中抽出横切关注点的位置(也就是核心方法),切入点是定位连接点的方式。
标注方式实现AOP:在切面类上注解@Aspect,然后spring配置文件添加<aop:aspectj-autoproxy/>
@Component @Aspect public class LoggerAspest { //任意参数类型,类中任意方法 @Before("execution(* aop.CalImpl.*(..))") public void before(JoinPoint joinpoint) { System.out.println("前置通知"); }}1
2
3
4
5
6
7
8
# 声明式事务
Jdbc.Template实现——Spring封装sql语句的实现类
@Transactional——注解式声明事务,添加注解的方法或者类会成为连接点