spring相关

Spring

对象.tostring = 对象实现类的类名 + @ +hashCode值,如果不重写对象tostring方法的话

service方法调用自己的方法,用this,这个this是原始对象,没有切入事务。 因为代理后 在handler里面的最终都是

advise前
target.invode(方法名) target 是原始对象
advise后
有两种方法可以,调用代理对象
1.expose-proxy=“true”
((AService) AopContext.currentProxy()).b();

2.也可以这么做 applicationContext.getBean().method 这个时候获得的bean 是代理对象

Spring只支持XML方式而没有实现注解的方式(也叫AspectJ方式)的AOP,所以要使用@Aspect注解,只能引入AspectJ相关的 jar 包 aopalliance-1.0.jar 和 aspectjweaver.jar。

CAP

Consistency:一致性,client1访问s1,写对象 0->1,client2访问s2,获取对象是1,就是一致
Availability:用户可以选择向 G1 或 G2 发起读操作。不管是哪台服务器,只要收到请求,就必须告诉用户,到底是 v0 还是 v1,否则就不满足可用性。

要保证的一致性,那么s1必须在写操作时,锁定 s2 的读操作和写操作。只有数据同步后,才能重新开放读写。锁定期间,s2 不能读写,没有可用性。如果保证 s2 的可用性,那么势必不能锁定 s2,所以一致性不成立。
所以AC是矛盾的

任何时刻对ZooKeeper的访问请求能得到一致的数据结果,所以是CP
比如说新增了一个服务A,无论从哪个zookeeper上都能读到A,有主的概念,上来一个服务后都不可能,选出主同步后才可用

对于eureka,新增了一个服务A,从某个eureka中心上可以读到A,从另一个可能读不到,因为eureka集群内的中心是平级的,互相同步不一定及时
所以是AP

服务提供者和中心要进行心跳,然后服务的访问者 维护一个服务组的缓存
zookeeper 都是主写,从读。
eureka没有主从

base理论:基本可用 最终一致。

服务器端负载均衡 Nginx
nginx 是客户端所有请求统一交给 nginx,由 nginx 进行实现负载均衡请求转发,属于服务器端负载均衡。
既请求由 nginx 服务器端进行转发。

客户端负载均衡 Ribbon
Ribbon 是从 eureka 注册中心服务器端上获取服务注册信息列表,缓存到本地,然后在本地实现轮询负载均衡策略。
既在客户端实现负载均衡。

Zuul 网关,是要请求转发,要负载还要用ribbon
nginx可以都实现

spring使用zuul和ribbon配置例子如下:
spring:
application:
name: api-gateway

server:
port: 8007
zuul:
routes:
user-service:
path: /user-service/**
serviceId: user-service2

ribbon:
eureka:
enabled: true
user-service2:
ribbon:
listOfServers: http://localhost:8003/,http://localhost:8004/

eureka:
client:
serviceUrl:
defaultZone: http://localhost:8002/eureka/

直接要取一个接口的泛型是取不到的,
例如
public interface IHe {
}

IHe.class 取得的是没有泛型的

要通过接口或者继承,

//Type是 Java 编程语言中所有类型的公共高级接口。它们包括原始类型、参数化类型、数组类型、类型变量和基本类型。
—继承
Type type=clazz.getGenericSuperclass();
//ParameterizedType参数化类型,即泛型
ParameterizedType p=(ParameterizedType)type;
Class c=(Class) p.getActualTypeArguments()[0] //取得泛型

—接口实现
Type[] types = clazz.getGenericInterfaces() //因为可以实现多个接口
for (Type type:types) {
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
//返回表示此类型实际类型参数的 Type 对象的数组
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
for (Type parameterArgType : actualTypeArguments) {
Class parameterArgClass = (Class) parameterArgType;
}

Spring后端返回一定是一个json字符串,不能是json对象,客户端通过ajax框架等,根据content-type为application/json,通过parse等转换成 json对象。

服务无状态 :多次请求和以前的请求无关。

利用泛型注入多个实例
@Autowired
private List demoServices;
@Autowired
private Map<String,DemoService> demoServiceMap;

Spring 会把 所有实现这个接口的DemoService的实例 都放入demoServices里

map,key为service的name value是实例

知识点1:appContext.getBeansOfType()方法。
该方法返回一个map类型的实例,map中的key为bean的名字,key对应的内容未bean的实例。
该方法有两种类型的重载:
getBeansOfType(Class),获取某一类的所有的bean。

Java的clone是浅copy,想要深拷贝 要 用字节流

Spring事务,是因为在service处 方法前增加了start 方法结束增加了end 提交事务
所以说在control里使用两个service 的话,就是两个事务了,因为上一个事务 已经结束了。

advise advice 都是通知的意思,前是动,后是名
实例化是创建对象。
初始化是创建对象后,对这个对象设定一些默认值

@Configuration 里面定义方法,返回bean类,相当于这个bean(CompService),在xml文件里这么定义了
@Configuration
public class TestConfig {

@Bean
public CompService compService(RemoteServiceClient remoteServiceClient) {
CompServiceImpl compService = new CompServiceImpl(remoteServiceClient);
return compService;
}

}

没有定义任何接口方法的接口叫做标识接口,例如Cloneable Serializable
主要是为了隔离解耦

spring事件:
1.首先定义一个事件
public class DemoEvent extends ApplicationEvent{} 里面写事件处理程序

2.定义一个监听
public class demoListener implements ApplicationListener{
/listener实现
public void onApplicationEvent(DemoEvent event) {
//这个地方写具体的业务

3.触发事件

@Component
public class DemoPublisher {

@Autowired
ApplicationContext context;
public void published() {
    DemoEvent event = new DemoEvent(this, "发布成功!");
    System.out.println("发部event:"+event);
    context.publishEvent(event);
}

}

ApplicationContextAware
常在bean加入注解扫描,或者在xml文件里定义都可以自动注入的,
但特殊情况,在某个bean中有一个静态方法,这个方法要调用一个spring管理的bean,因为这个静态方法是不能访问类变量的(注入类的对象都是类变量),所以在内部通过

还有一种情况是没有通过spring容器管理的javabean,通过包名+类名,放到容器中
通过容器 applicationContext.getBean()获得,这个方法先在容器内查询有没有这个bean,没有通过加载器加载,然后实例化。

BeanNameAware
接口有一个方法setBeanName,可以给这个bean起一个业务的名字

BeanPostProcessor 简称BPP,是spring AOP实现根源
接口有两个方法,postProcessBeforeInitialization和postProcessAfterInitialization,参数为bean和beanname,
对容器内的每一个bean做一个些处理,比如生成一个代理等等 org.mybatis.spring.mapper.MapperScannerConfigurer

FactoryBean
  以Bean结尾,表示它是一个Bean,不同于普通Bean的是:它是实现了FactoryBean接口的Bean,根据该Bean的ID从BeanFactory中获取的实际上是FactoryBean的getObject()方法返回的对象,而不是FactoryBean本身,如果要获取FactoryBean对象,请在id前面加一个&符号来获取
他是一个接口,比如SqlSessionFactoryBean就继承于它,主要用于构建复杂的对象

getObject 方法可以放回一个字符串,例如
dbPassword 就是一个实现了FactoryBean接口

destroy-method和init_method,标签 后面可以指定 方法
在实例化后和销毁前调用,
例如:init-method=“init”

在实例化的时候,如果没有定义构造函数,会默认加一个无参数的构造函数,如果已经有了无论有没有参数都不需要加了。
属性注入,不是实例化,而是在实例化后执行一个属性方法。

服务注册,寻址,负载,拆分,熔断,分布式锁

(1):如果bean的scope是singleton的,并且lazy-init为false(默认是false,所以可以不用设置),则 ApplicationContext启动的时候就实例化该Bean,并且将实例化的Bean放在一个map结构的缓存中,下次再使用该Bean的时候, 直接从这个缓存中取
(2):如果bean的scope是singleton的,并且lazy-init为true,则该Bean的实例化是在第一次使用该Bean的时候进行实例化
(3):如果bean的scope是prototype的,则该Bean的实例化是在第一次使用该Bean的时候进行实例化

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.java:

//……//在一个bean的合作者设备完成后,执行一个bean的初始化方法。
protected void invokeInitMethods(String beanName, Object bean, RootBeanDefinition mergedBeanDefinition) throws Throwable
{

//判断bean是否实现了InitializingBean接口
if (bean instanceof InitializingBean)
{if (logger.isDebugEnabled())
{
logger.debug(“Invoking afterPropertiesSet() on bean with name ‘” + beanName + “‘”);
}
//调用afterPropertiesSet方法
((InitializingBean) bean).afterPropertiesSet();
}
//判断bean是否定义了init-method
if(mergedBeanDefinition!=null&&mergedBeanDefinition.getInitMethodName() != null)
{
//调用invokeCustomInitMethod方法来执行init-method定义的方法
invokeCustomInitMethod(beanName, bean, mergedBeanDefinition.getInitMethodName());
}
}
//执行一个bean定义的init-method方法p
rotected void invokeCustomInitMethod(String beanName, Object bean, String initMethodName)throws Throwable
{
if (logger.isDebugEnabled())
logger.debug(“Invoking custom init method ‘” + initMethodName +"‘ on bean with name ‘" + beanName + “‘”);
}
//使用方法名,反射Method对象

Method initMethod = BeanUtils.findMethod(bean.getClass(), initMethodName, null);

if (initMethod == null)
{
throw new NoSuchMethodException(

“Couldn‘t find an init method named ‘” + initMethodName + “‘ on bean with name ‘” + beanName + “‘”);
}
//判断方法是否是public
if (!Modifier.isPublic(initMethod.getModifiers())) {//设置accessible为true,可以访问private方法。 initMethod.setAccessible(true);}
try {
//反射执行这个方法initMethod.invoke(bean, (Object[]) null);
}catch (InvocationTargetException ex)
{throw ex.getTargetException();}}//…………

通过分析上面的源代码我们可以看到,init-method是通过反射执行的,而afterPropertiesSet是直接执行的。所以 afterPropertiesSet的执行效率比init-method要高,不过init-method消除了bean对Spring依赖。在实际使用时我推荐使用init-method。
需要注意的是Spring总是先处理bean定义的InitializingBean,然后才处理init-method。如果在Spirng处理InitializingBean时出错,那么Spring将直接抛出异常,不会再继续处理init-method。
如果一个bean被定义为非单例的,那么afterPropertiesSet和init-method在bean的每一个实例被创建时都会执行。单例 bean的afterPropertiesSet和init-method只在bean第一次被实例时调用一次。大多数情况下 afterPropertiesSet和init-method都应用在单例的bean上。

initializingBean接口是spring提供的,子类要实现afterPropertiesSet()方法,init-method是用户可以通过属性文件配置的。从这里可以看出实现initializingBean接口是要和spring耦合的,而init-method则不会。但afterPropertiesSet()方法spring可以直接调用执行,init-method指定的方法却需要通过反射来执行,从效率来上讲没有afgerPropertiesSet()快。InitializingBean和init-method可以一起使用,Spring会先处理InitializingBean再处理init-method。

把spring返回的bean对象转换成json字符串,返回到前端,前端通过ajax等把json字符串转换成json对象,这样就需要一个转换器
实现了HttpMessageConverter接口

配置了mvc:annotation-driven,就自动加载下面的bean了,用于前后台json和对象的转换



text/plain;charset=UTF-8



对于spring以外的框架,需要自己做json之间的转换,比如cxf,thrift等等

配置这个后不需要在class里加上 @resource 或者 @autoired 注解了

一种是通过标签,一种是通过注解

resource 注解 通过名字来获得bean

  1. bpp的两个方法是有返回值Object的,这恰恰是问题的关键,这个bean就是我们要修改的bean,这样一来,我们就可以修改bean实例本身,或替换,或wrap成一个proxy bean(Spring中的aop机制多是这么干),而其它的初始化接口的返回为void,因此它们理论上只能修改bean的状态,能做的东西相当受限制。
  2. bpp是以扩展插件的形式被Container执行,不需要bean本身去做什么(bean本身不用实现这个接口),所以这个插件跟bean在代码上不耦合
  3. 在执行方式上也完全不同,bpp是作为Spring container的一个扩展,在容器初始化bean的过程过,对每个bean都会执行一次,而初始化接口,由于是特定的bean实现的,所以与其它的bean无关,只对初始该类型的bean执行。简而言之就是,虽然都是由容器执行对bean的操作,bpp是扩展的容器本身行为,而初始化接口是扩展bean的行为后被容器执行的。

@Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入;
@Autowired默认是按照类型装配注入的,如果想按照名称来转配注入,则需要结合@Qualifier一起使用;
@Resource注解是又J2EE提供,而@Autowired是由Spring提供,故减少系统对spring的依赖建议使用@Resource的方式;
@Resource和@Autowired都可以书写标注在字段或者该字段的setter方法之上。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值